Common problems
StartCoroutine
can only be called from the main thread in Unity
Sometimes you want to start Unity coroutine in a handler of the EventReceived event of InputDevice. Your code can be executed on a separate thread in this case. It can happen because events are received by device on a separate (system) thread.
But UI related things like call of StartCoroutine
can be executed on UI thread only. You can use the solution from here: https://stackoverflow.com/a/56715254.
Related question on StackOverflow: Catching and processing multiple keyboard inputs at once
InputDevice
declared as a local variable
If an instance of the InputDevice is declared as a local variable and you’ve subscribed to its EventReceived event, the event handler won’t be called or you can get undefined behavior. For example, let’s look at this code:
private void StartListening()
{
var inputDevice = InputDevice.GetByName("My Device");
inputDevice.EventReceived += OnEventReceived;
inputDevice.StartEventsListening();
}
private void OnEventReceived(object sender, MidiEventReceivedEventArgs e)
{
// Do something ...
}
What happens when the StartListening
method exits? Right, all local variables are marked as ready for garbage collection, so they will be deleted within a short time span. So the OnEventReceived
method becomes attached to a deleted entity (inputDevice
) when the StartListening
exited. In the best case you just won't get OnEventReceived
called. In worst case you may get different strange things, see this issues:
Input device must be stored in a class field:
private InputDevice _inputDevice;
private void StartListening()
{
_inputDevice = InputDevice.GetByName("My Device");
_inputDevice.EventReceived += OnEventReceived;
_inputDevice.StartEventsListening();
}
And don't forget to dispose of the device when you're done with it. Please read the Input device article to learn more.