Using control schemes without PlayerInput?

Pretty specific situation here, so bear with me. I’m working on a game that is VR vs PC on a local machine, in the sense that one player plays in VR, and the other(s) play on PC using standard inputs (MKB, Gamepad). Here’s a short GIF for clarification.

We currently support the ability to add multiple PC players via split screen (for now there is only one VR player), where each PC player has a PlayerInput. The VR player does not, since up until now there’s been no need, but that has changed due to the following:

I want to make several VR control schemes, each for specific devices (Oculus, Vive Wand, WMR), and then a final “device agnostic” control scheme that would use the OpenVR bindings (RightHandXRController and so on). Targeting specific devices with tailored control schemes really helps make each device fit the game.

Ideally, the VR player would select the control scheme for its specific device if it exists, and if not, select the generic VR control scheme.

Problem A) If I use PlayerInput with the VR player, when there is only a single PC player they can no longer auto switch between the Gamepad and PC schemes (this is undesirable).

Problem B) I’m not entirely sure how to select a control scheme without PlayerInput. Right now for the VR player I just grab a new instance of my InputActions, and then subscribe to all the events. E.g.,

InputActions inputActions = new InputActions();
inputActions.Giant.GrabRight.performed += blahblahblah

But I don’t think InputActions has any way of limiting it to a specific control scheme. Is there currently a best practices way to do this?

Thanks for any help,
Erik

You can use control scheme directly with InputUser using _yourInputUser.controlScheme.Value.
Maybe you can simply check for the active controlScheme on your callback to differentiate your logics ?

Game looks really fun !

The current control scheme selection indeed falls short here. Improving this to allow for selection between ambiguous schemes is on the list for after 1.0.

For now, the only way to guide this is by order in which control schemes are listed. For which no direct control exists in the UI other than creation order.

If schemes appear in order of decreasing specificity (i.e. generic fallback scheme comes last), control scheme selection should do the right thing even with what’s there ATM. But yeah, needs improvement. Hardly elegant this way.

Why not? If there’s only a single PlayerInput in the game and the player has multiple control schemes available on the actions but doesn’t auto-switch, that sounds like a bug. Note, however, that switching can only be initiated from controls that aren’t considered noise. For VR specifically, that means that simply putting on the headset and picking up the VR controller won’t do the trick (except if you’ve bound the userPresence kind of controls, though I believe some one or two of them erroneously have the noise flag on them ATM).

The mechanisms used by PlayerInput (indirectly through InputUser) are available on all InputActionAssets/Actions/Maps but ATM there’s no nice wrappers so it requires jumping through some hoops.

The basic mechanism is to restrict the set of bindings that are considered active by setting what’s called a “binding mask”.

inputActions.bindingMask = InputBinding.MaskByGroup("VR");

The name of the group usually corresponds to the name of the control scheme. You can read out the bindingGroup property on the schemes available from the controlSchemes property to look up a name dynamically if need be.

Note that restricting the bindings on actions alone is usually not enough. You also would want to restrict the set of devices that the actions pick their controls from. This can be achieved by assigning the devices to the ‘devices’ property.

inputActions.devices = new[] { XRHMD.current, XRController.current };

Overall, if you want to bypass PlayerInput but do want to have multiple players, would recommend making use of the InputUser API as it manages a lot of details for you. It’s what PlayerInput is built on.

Sorry if I wasn’t 100% clear, but I was describing a case where I would be using a PlayerInput for both the giant and PC players (the game is local multiplayer). There is always only a single giant, but can have one or more PC players, which is why I use PlayerInput for the PC players right now. So the current setup for 1 VR vs 1 PC player is: the VR player does not use PlayerInput, but the PC player does (to support multiple PC players). However, if I put a PlayerInput on the giant (just to select the control scheme), then in 1 vs 1 the PC player can no longer auto switch between MKB and Gamepad, since PlayerInput thinks there are “two” players (which there are, but they target different devices). Sorry if this is a bit confusing!

The binding mask looks like it would work for my situation with a bit of extra code, thanks for the response.

1 Like