Setting up joysticks (or any device) with specific roles is possible and can be used inside the bindings for actions as well as with OnScreenControls.
Any device has an arbitrary set of “usages” that can be applied to it. These are just string tags that can be applied dynamically at runtime using InputSystem.SetDeviceUsage or InputSystem.AddDeviceUsage.
One way to exploit these usages is with the path strings. You can drop a binding into text mode with the little T button and then type stuff like “{Left}/trigger” (binds to the “trigger” control of the device of type Joystick which is tagged with the “Left” usage).
However, a far more elegant way is to tell the system about the usages you intend to use. If you do this, this will show up in the control picker as well. You can apply this to any existing layout in the system through what’s called a “layout override”. Check out the “Custom Device Usages” sample for a working sample of this.
// Let's say you want to have two joysticks. One tagged
// with "Left" and one with "Right".
InputSystem.RegisterLayoutOverride(@"
{
""name"" : ""JoystickWithUsageTags"",
""extend"" : ""Joystick"",
""commonUsages"" : [
""Left"", ""Right""
]
}
");
This override causes the settings you apply to directly write over the built-in Joystick layout. With this done (somewhere in the startup sequence), you will see the following in the control picker.

Now you can bind specifically to the left and the right joystick individually. This works in .inputactions files but also wherever else the control picker is used. I.e. also with OnScreenControls.
Also, this allows setting up control schemes that specifically require a Left and a Right joystick, for example.
There is one more step missing, though. At runtime, you need to actually assign the usages to joysticks for the bindings to become active.
InputSystem.SetDeviceUsage(joystick1, "Left");
InputSystem.SetDeviceUsage(joystick2, "Right");
The way OnScreenControl works ATM, it will have an inherent one-frame lag. Something we should probably fix.
////EDIT: I just realized that OnScreenControls will not create the devices with these usages correctly. Looking at the code, I found an existing FIXME in there about this. ATM the code ignores usages in the paths and does not apply them to the devices. I’ll have a look at that.