Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Bug WithControlsExcluding excludes more actions than intended. I also included a fix for it. (v1.3.0)

Discussion in 'Input System' started by larssonmartin1998, Jul 14, 2022.

  1. larssonmartin1998

    larssonmartin1998

    Joined:
    Dec 12, 2017
    Posts:
    9
    Hey,

    I've noticed that if I run PerformInteractiveRebinding().WithControlsExcluding("<Keyboard>/backspace") it will also exclude the B bind as well as backspace.

    This goes for all the similar cases, such as:

    Code (CSharp):
    1.  
    2. WithControlsExcluding("<Keyboard>/enter") // also excludes E binding.
    3. WithControlsExcluding("<Keyboard>/escape") // also excludes E binding.
    4. WithControlsExcluding("<Keyboard>/anyKey") // also excludes A binding.
    5. WithControlsExcluding("<Keyboard>/leftMeta") // also excludes L binding.
    6. WithControlsExcluding("<Keyboard>/rightMeta") // also excludes R binding.
    7.  
    8. // You get the point.
    9.  
    Here is the original code:
    Code (CSharp):
    1.  
    2. private static bool ComparePathElementToString(Substring pathElement, string element)
    3. {
    4.     var pathElementLength = pathElement.length;
    5.     var elementLength = element.Length;
    6.  
    7.     for (int i = 0, j = 0;; i++, j++)
    8.     {
    9.        var pathElementDone = i == pathElementLength;
    10.        var elementDone     = j == elementLength;
    11.  
    12.        if (pathElementDone || elementDone)
    13.            return pathElementDone == elementDone;
    14.  
    15.        var ch = pathElement[i];
    16.        if (ch == '\\' && i + 1 < pathElementLength)
    17.            ch = pathElement[++i];
    18.  
    19.        if (char.ToLowerInvariant(ch) != char.ToLowerInvariant(element[j]))
    20.            return false;
    21.    }
    22. }
    23.  
    Essentially, it runs to the last line of the loop at compares 'b' to 'b' in "backspace", then the path of 'b' is finished and the loop ends, without finding a mismatch.

    I just escaped the pathElement before the char comparison and compared their word lengths. If they're the same length, we then compare every character to each other. Here is my fix:

    Code (CSharp):
    1.  
    2. private static bool ComparePathElementToString(Substring pathElement, string element)
    3. {
    4.     var pathElementLength = pathElement.length;
    5.     var elementLength = element.Length;
    6.  
    7.     // `element` is expected to not include escape sequence. `pathElement` may.
    8.     // So if `element` is longer than `pathElement`, the two can't be a match.
    9.     if (elementLength > pathElementLength)
    10.         return false;
    11.              
    12.     string escapedPathElement = string.Empty;
    13.     for (var i = 0; i < pathElementLength; ++i)
    14.     {
    15.         var ch = pathElement[i];
    16.         if (ch == '\\' && i + 1 < pathElementLength)
    17.             ch = pathElement[++i];
    18.  
    19.         escapedPathElement += ch;
    20.     }
    21.  
    22.     // Check if 'element' and 'pathElement' have different lengths after escaping pathElement.
    23.     // If they're not the same length, they're not the same path.
    24.     pathElementLength = escapedPathElement.Length;
    25.     if (elementLength != pathElementLength)
    26.         return false;
    27.              
    28.     for (var i = 0; i < pathElementLength && i < elementLength; ++i)
    29.     {
    30.         if (char.ToLowerInvariant(escapedPathElement[i]) != char.ToLowerInvariant(element[i]))
    31.             return false;
    32.     }
    33.  
    34.     return true;
    35. }
    36.  
    I would just create a pull request for this, but they required me to run bunch of unit tests, edit their changelog and more, so I figured I'd just drop the fix here for anyone that is interested.

    Hope anyone can find this useful, and hopefully they can get this officially fixed soon.

    Happy game making :)

    P.S: I'm not able to create new Tags, and the only ones available seems to be documentation and performance, that’s stupid. So if a forum admin sees this post, feel free to add tags which makes sense so that people who have this problem can actually find it :)

    EDIT: I just realised that they've released 1.4 of the Input System. I'm running a custom fork of the 1.3 as I've added some custom stuff for my game like setting an actions category & bindings description from the editor which I use to generate a keybinding menu. In other words, maybe this is fixed in 1.4? Not sure, but if someone feels like it, please try it on 1.4 and put in a comment if it's bugged there or not.