[REQUEST] Add Single Click Relative to Double Click for Input

WeiYiHua

Member
In many cases, it might be necessary to bind both a double click and a single click of the same key to different functions. However, UCC is unable to distinguish between a double click and a single click relative to it.

Below is the method I have added, called GetSinglePress:

Code:
/// <summary>
/// Returns true if a double press occurred (double click or double tap).
/// </summary>
/// <param name="buttonName">The button name to check for a double press.</param>
/// <returns>True if a double press occurred (double click or double tap).</returns>
public bool GetDoublePress(string buttonName)
{
    if (GetButtonDown(buttonName)) {
        if (m_ButtonDownTime == null) {
            m_ButtonDownTime = new Dictionary<string, float>();
        }
        if (m_ButtonDownTime.TryGetValue(buttonName, out var time)) {
            if (time != Time.unscaledTime && time + m_DoublePressTapTimeout > Time.unscaledTime)
            {
                m_ButtonDownTime.Remove(buttonName);
                return true;
            }
            m_ButtonDownTime[buttonName] = Time.unscaledTime;
        } else {
            m_ButtonDownTime.Add(buttonName, Time.unscaledTime);
        }
    }

    return false;
}

/// <summary>
/// Returns true if a single press occurred (As opposed to double press).
/// </summary>
/// <param name="buttonName">The button name to check for a single press.</param>
/// <returns>True if if a single press occurred (As opposed to double press).</returns>
public bool GetSinglePress(string buttonName)
{
    if (m_ButtonDownTime == null)
    {
        m_ButtonDownTime = new Dictionary<string, float>();
    }
    if (m_ButtonDownTime.TryGetValue(buttonName, out var time))
    {
        if (time != Time.unscaledTime && time + m_DoublePressTapTimeout <= Time.unscaledTime)
        {
            m_ButtonDownTime.Remove(buttonName);
            return true;
        }
    }

    return false;
}

Support for the SinglePress Input can also be incorporated within the Ability.1691571718830.png

1691571712494.png
 
By the way, it is suggested to change the private variables and methods in the PlayerInput class to protected to facilitate more flexible control by subclasses.
 
Thanks! That looks doable to add, I'll include it in the next update. Thank you! I will also make more input variables protected.
 
Just giving you a heads up that I am delaying this until version 3.1. With the enum change it will cause all subsequent enum values to get changed so I want to wait until a feature update release to make this type of change. It's on my list though to definitely be included in 3.1.
 
This version of GetSinglePress can be used without GetDoublePress.
Code:
/// <summary>
/// Returns true if a single press occurred (As opposed to double press).
/// </summary>
/// <param name="buttonName">The button name to check for a single press.</param>
/// <returns>True if if a single press occurred (As opposed to double press).</returns>
public bool GetSinglePress(string buttonName)
{
    if (m_ButtonDownTime == null)
    {
        m_ButtonDownTime = new Dictionary<string, float>();
    }
    if (m_ButtonDownTime.TryGetValue(buttonName, out var time))
    {
        if (time != Time.unscaledTime && time + m_DoublePressTapTimeout <= Time.unscaledTime)
        {
            m_ButtonDownTime.Remove(buttonName);
            return true;
        }
    }
    else if (GetButtonDown(buttonName))
    {
        m_ButtonDownTime.Add(buttonName, Time.unscaledTime);
    }

    return false;
}
 
I am looking at this now for version 3.1. What is the difference between a ButtonDown and SinglePress? Just that you have the option of specifying a timeout?
 
The same key will only trigger either a single click or a double click within the same time period. Therefore, the single click will wait for m_DoublePressTapTimeout to ensure that no double click is triggered during this time.
 
Makes sense. Ok, in version 3.1 I added a new bool in the ability called Wait For Double Press Tap Timeout. This bool will be checked in PlayerInput.GetButtonDown. I did it this way so I didn't have to add another enum to the list and reduce confusion. I ended up using the same code posted here within GetButtonDown.
 
I'd like to propose a different perspective. Perhaps it would be better to have a separate SinglePress enumeration specifically for Inputs that require a single click, as there is a delay associated with a single click. For certain button down, I may want them to trigger immediately in this frame, whereas for buttons with single click and double click, I may want to ensure that single click and double click do not conflict.
 
With this bool you can do that. By default it'll be off, and with that the button down is checked that frame. If it is on then it will wait to ensure the double press doesn't conflict.
 
If "Wait For Double Press Tap Timeout" is only used as an input parameter for the "GetButtonDown" method, then indeed, it aligns appropriately with the suggestion above. However, you would still need to add a boolean variable in places like "Ability." If "Wait For Double Press Tap Timeout" becomes a member variable of "PlayerInput," it would introduce a delay for all "GetButtonDown" calls.
 
Wait For Double Press Tap Timeout is on the ability, and is passed into the PlayerInput. This will allow each ability to decide how to use it. This parameter is not used outside of the ability system.
 
That approach is also viable. In my practice, I lean towards directly supporting SinglePress in all places using PlayerInput without adding additional boolean variables.
 
Top