According to Unity Cloud Diagnostics, my game randomly starts throwing the following exceptions after the game ran without error for several hours before.
This problem occurs on Android phones and I’m unable to reproduce the problem locally.
Any idea how to reproduce it?
Any idea how to fix/workaround it?
What is the error actually telling me and how severe is the problem?
NotSupportedException while resolving binding 'Move:<Keyboard>/rightArrow[;Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):Player'
NotSupportedException while resolving binding 'Navigate:<Keyboard>/rightArrow[Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):UI'
NotSupportedException while resolving binding 'Move:<Keyboard>/rightArrow[;Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):Player'
NotSupportedException while resolving binding 'Navigate:<Keyboard>/rightArrow[Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):UI'
Please note that the issue occurs on different Android devices with different OS’s. The exception and callstack don’t help me further. Can you extract from it where the problem lies?
Something must be adding more and more devices to the point where a single binding ends up resolving to more than 255 controls. Looking at the binding, it would seem that by that point 255 keyboards have been added.
The most common cause for this is script code that manually does AddDevice over and over and never removes the devices. But the stack above looks like the device was actually reported by the Android backend. Which makes me suspect something must be misbehaving there.
Android has a weird thing where the type of a device is a flag. And all kinds of devices end up reporting themselves as keyboards. But even then, for this to be the cause, it’d have to report a new keyboard device over and over and over.
Another thing that puzzles me is that looking at your PlayerInput and action configuration, even having a thousand keyboards shouldn’t matter. With control schemes and auto-switch being used, it should always track only the actively used devices and thus never try to resolve a <Keyboard>/rightArrow from all keyboards that have been reported.
Is the above PlayerInput action setup the only way you are using those actions? Or by chance, do you happen to have “Generate C# Class” on and are using that one as well?
Here is the InputActionsUtility code. It outputs the number of InputActions each time a level was loaded. It’s 4 InputActions in a level and 2 InputActions in the mainmenu. Switching levels doesn’t increase the number of InputActions, there doesn’t seem to be a leak, I just tested it.
public static class InputActionsUtility
{
static int s_Count;
[RuntimeInitializeOnLoadMethod]
static void RuntimeInitializeOnLoadMethod()
{
s_Count = 0;
Loading.scenesLoaded -= OnScenesLoaded;
Loading.scenesLoaded += OnScenesLoaded;
}
static void OnScenesLoaded()
{
Dbg.Log(null, $"{s_Count} InputActions created");
}
public static InputActions Create()
{
var obj = new InputActions();
s_Count++;
return obj;
}
public static void Destroy(InputActions obj)
{
if (obj == null || obj.asset == null) return;
s_Count--;
obj.Disable();
// If we call Dispose() in OnDisable() while the editor exists playmode,
// Unity outputs an error that you must use DestroyImmediate instead.
// So this is our workaround here.
if (Application.isPlaying)
obj.Dispose();
}
}
Ah, so that would explain the “why are actions trying to grab all keyboards instead of one” part. The code generated by “Generate C# Class” will by default resolve against the full list of devices available through InputSystem.devices. This can be restricted manually through the devices property but unlike PlayerInput, the code here doesn’t do any control scheme switching. So with 256 keyboards in InputSystem.devices, “/rightArrow” would resolve to 256 controls.
In general, when using PlayerInput, it’s best not to also use “Generate C# Class”.
However, the real bug would still be the fact there are >255 keyboards in the first place. It very strongly looks like something in the Android backend causing that. A bug report for this one would be appreciated.
How can I workaround the issue? You mention I could restrict the available devices through a “devices property”, but how? The game is heavily relying on the “Generate C# Class” thing, it’s not an easy task for me to get rid of it.
Is submitting a bug-report going to help, when I don’t have a project where you can reliably reproduce the issue? I’m not able to reproduce this issue at all for example. So far any bug-report I submitted without a 100% reproduction case didn’t lead to anything.
var actions = new MyGeneratedActions();
actions.devices = new InputDevice[] { Keyboard.current };
This is the part that unfortunately, compared to PlayerInput, has to be managed manually.
Ah, hmm, that indeed complicates things. I was under the impression that simply running the app for several hours inevitably leads to the problem. Is there by chance a pattern to the devices (brand?) on which the problem occurs?
The “Control count per binding cannot exceed byte.MaxValue=255” problem seems to occur on iPad7,11 with iOS 15.3.1 only, according to Unity Cloud Diagnostics.
I found the following warning in those reports that Cloud Diagnostics collected:
Received stylus event from a device which shouldn't have supported it. Check IsStylusTouchSupported implementation
This warning doesn’t come from our code, probably from Unity or InputSystem. Is it any helpful?