Any way to get the control scheme for an input through InputAction.CallbackContext ?

Hello!

I’ve setup a nice workflow where I simply listen to input events in the script, I like it that way. However, now I want to know which control scheme(s) my player is using in a flexible manner: is it Mouse&Keyboard or Gamepad?

I understand there is an event (PlayerInput.OnControlsChanged) for that, but I either couldn’t hook to it or it won’t fire, I believe it is because I don’t instantiate a PlayerInput because I don’t need to and don’t want to because I dislike/don’t understand well the workflow using the PlayerInput component.

So, get/set the control scheme without using the component approach? Or alternatively is there any plan to include this functionnality?

That’s a tough one. I can’t think of a graceful way to determine the control scheme without hardcoding.

Usually, if you wanted to do a barebones approach that uses control schemes, you would create an InputUser on your player or some input management class and associate that user with an InputActionMap. You would then pair the InputUser with a devcie using onUnpairedDeviceUsed.

At that point, your InputUser would have access to the control schemes in the map, and could keep track of which control scheme you are using.

PlayerInput effectively wraps InputUser and provides few extra features for interfacing with it. If you are interested to learning how this process works, I would advise dissecting the PlayerInput class and seeing how it works. There is actually quite a lot of noise in the PlayerInput class, making it seem like working with InputUser is daunting. It’s actually pretty straightforward once you can wrap your head around all the terms.

Back to your question, without an InputUser or a PlayerInput, the only other way you could know which control scheme is active is checking the control’s displayName and checking to see if the beginning of the name starts with “Keyboard” or “Gamepad”. Theoretically, this would tell you which device this control is bound to, but not the control scheme. You could infer the control scheme from there. It would work, but it would be a bit hacky and you aren’t actually using any control schemes when you do this.

Still, if you are not doing multiplayer, then this might be the quickest way to accomplish what you’re asking.

A feature that would fit my use case would be to have a list of control schemes registered to an input.

Indeed my use case is on a single-player game and I acknowledge it would not readily fit with a multi-player game, although I believe the suggestion I am about to make would certainly help a lot. (When one don’t want to use the PlayerInput)

Theoretically, when the input.performed is fired, it knows the whole context: exactly which key has been pressed to allow the firing of this performed event (Although I have yet to find a way to retrieve it at the exposed level). As well as which action has been listened to, so it should be able to retrieve the exact entry in the InputAction database that is associated with the performed event. In this case it should also be able to retrieve the control scheme(s) associated with this entry?

Having access to this information would be nice and would be a bit better and more “official” than having to create different inputActions to “simulate” different schemes as I think you suggested.

Anyways, thanks! I’ll be using the “different inputActions” approach, and will keep hoping a more “official” approach will be developed by the end of the project :stuck_out_tongue:

Hi,
Sorry for bringing back this old thread, but I have the same question.
But my use case is slightly different so the “workaround” doesn’t work for me.

I’m making a 4 local multiplayer game. To make it more accessible we want to allow two players to be able to play on a single keyboard in case they don’t have a gamepad available.

I do not use PlayerInput because it was too limiting, I wrote my own system which gives me a lot more control.

My current approach (that works for gamepads and one player on the keyboard) is to wait for player input to join. They must press the “join” button.
Once they do I check the device and create a player assigned to that device with a duplicate InputActionAsset which only have that device linked to it.

To allow two players on one keyboard I’d need to know within InputAction.CallbackContext if it was triggered by controlScheme “KeyboardPlayer1” or “KeyboardPlayer2”.

I have some workaround in mind, but if it was possible to get the control scheme from the callback it would really simplify things.

I’m using InputSystem 1.3.0 and (Unity 2020.3), I don’t want to update because I’m close from releasing the game.

1 Like

Anyone managed to do this? Seems it should be so easy…

Yeah, another of those “should be easy” things.

You can get to the data, but it’s only in a roundabout way:

// Get control that triggered from the context.
var control = ctx.control;

// Get the binding for it.
var binding = ctx.action.GetBindingForControl(control).Value;

// Now "binding.group" contains the name of the scheme. In case
// the binding is assigned to more than one, it's a semicolon-
// separate list (like "Keyboard;Gamepad").
Debug.Log(binding.groups);

Thanks for the reply!
Yes, that is a bit roundabout, I actually managed to do what I needed (check if the input method changed) by checking the display name of the control’s device instead:

callbackContext.control.device.displayName

Just to add to this, it would be great to have a way to get the input action control type without it being triggered. I’m currently trying to hook up button prompts across a game and it’s not appropriate to wait untli the button is pressed to show the correct button prompt. In my case a page up/down action can be bound to either shoulder buttons in a positive/negative “Axis” type or to left/right on the stick as part of a “Vector2” type. It depends on the context of the page and much of the UI is procedural so it’s a real pain for me to work around.