Multiple players on Keyboard (New Input system)

Not working for me. I have a single-player game, where multiple gameobjects are using one keyboard. I have made separate Input Action Assets for all of them and assigned them to each gameobject. Only one gameobject is getting input actions.

Why this is so? Splitting input actions to several gameobjects such be a standard operations. I don’t see any reason why this is not working or why should we use work-arounds to build a basic setup.

EDIT :

And the solution seems to be ditching the Player Input component and instead hook up one Input Action Asset in code like :

public class GameObjectController : MonoBehaviour
{

    public InputActionAsset inputActionsAsset; 

....


  void Start()
    {

        inputActionsAsset.Enable();

        InputAction move = inputActionsAsset.FindAction("Move");

        move.started += OnStart;
        move.canceled += OnStart;

...

  private void OnStart(InputAction.CallbackContext context)
    {
        isStarted = true;
    }

It seems that this is possible to do on several game objects and with overlapping controls.

There are some examples in
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Actions.html

PlayerInput, if not manually forced to do otherwise, will grab devices for exclusive use. So, even if there’s multiple separate sets of .inputactions, the first PlayerInput ending up with the keyboard will prevent other PlayerInputs from being able to “claim” it. The way around this is to either manually spawn PlayerInputs as in my post way up there or to force PlayerInputs onto a device after the fact.

PlayerInput.all[0].SwitchCurrentControlScheme("KeyboardWASD", Keyboard.current);
PlayerInput.all[1].SwitchCurrentControlScheme("KeyboardArrows", Keyboard.current);
3 Likes

Yes, this worked perfect for me in the editor. However, when creating a build only one of the players (the WASD one in particular) managed to actually work. The ARROW one couldn’t be able to be linked to the keyboard. I’m still not sure how exactly It managed to work in the editor and not in the final build. Instead I used:

InputUser.PerformPairingWithDevice(Keyboard.current, user: playerWASD.user);
InputUser.PerformPairingWithDevice(Keyboard.current, user: playerARROW.user);

The input system is already at version 1.2.0 and apparently it still doesn’t support this, contrary to what was stated here almost 3 years ago.
I’ve tried the method suggested at the beginning of this thread, using PlayerInput.Instantiate, but even though I’ve passed the intended control scheme and device, it ends up instantiating a PlayerInput with no control scheme and player device assigned.

So, what I did as a workaround was casting the instantiated component onto a variable, and then force the control scheme switch.
It seems to work, at least in the editor (haven’t tested a build yet).

My final code is this:

var player = PlayerInput.Instantiate(_playerPrefab, controlScheme: controlScheme, pairWithDevice: device);
player.SwitchCurrentControlScheme(controlScheme, device);

Sorry to revive a dead thread, but does work if the two players do different things? If I want to say, “these four buttons are yours, these four are theirs”, and those four do different things for both people… what then?

As far as this script is concerned, it just creates 2 “Keyboards” and remaps keys for you. IE: Virtual Keyboard #1 thinks WASD is arrow keys, Virtual Keyboard #2 thinks IJKL is arrow keys. It doesn’t care what you do with them.

1 Like

Any update on officially supporting this in the Input System? seems like a pretty common feature to want local multiplayer using one keyboard… I tried the provided workarounds by Rene-Damm and no luck for both editing the PlayerInput after instantiation and spawning it in manually…

bump?

Another promise that will never happen?

I recently had this problem, and found a solution that lets you retain the good stuff about PlayerInputManager whilst adding support for shared keyboard input across multiple players. The solution isn’t ideal since it requires some (very minimal) modifications to the Input System package, but it’s easy to do, and with some additional work you could make it as flexible as you need.

I wrote about it here and the gist is here

Long story short, you just need to change some signatures in PlayerInputManager and it’s associated inspector, and you’ll be back up and running in no time :partying_face:

@luycaslima I believe I found the solution on how to assign multiple players to a keyboard, after a lot of frustration. I still need to test with other button inputs besides movement but my solution seems to be working for movement so far.

Firstly,

Beginning with the Input Actions, create an action map and map both the WASD and Arrow Keys to the “Move” action or whatever you’re calling the action. I made up mine with two 2D Vector’s after setting the action type to “value” and Control type to “vector2”.

Then create two Control Schemes, each named for the the control type you want to use and require the keyboard in the list (e.g KeyboardWASD for WASD control, and KeyboardArrows for Keyboard Arrows control). Go back to “All Control Schemes Tab”, and then for each of the Up/Down/Left/Right keybinds, click on the checkmark of the WASD scheme for one of the 2D Vectors, and do the same for the Arrows scheme. Basically, all keybinds that are going to be used in a specific scheme’s 2D vector need to have their checkbox checked for all of the necessary controls they need.

(A keybind within the Arrows 2D Vector has the KeyboardArrows scheme checked)

(A keybind within the WASD 2D Vector has the KeyboardWASD scheme checked)

That should complete all of the necessary steps for the PlayerInput portion

Secondly,

On the Two Gameobject/Prefabs, add a Player Input component and assign the previously created PlayerInput object into the Actions variable. Assuming the players are already in the scene, in the default scheme dropdown, switch one over to the WASD Scheme and the other to the Arrows Scheme. One important thing, make sure to switch the behavior to Invoke Unity Events.

(WASD player PlayerInput Component’s Default Scheme)

(Arrows player PlayerInput Component’s Default Scheme)

Before getting to the Unity Events, go to your Player or Controller script. Declare a public method with a Callbackcontext variable. Implement a Vector2/3 variable that can store input from your keyboard. My implementation, its called OnMove, and it assigns the Vector2 player input into a variable called move direction, to be used in a move function shown below.
EDIT 1: also make some conditional logic to decide which gameobject gets which control scheme, for me i just did a gameobject name check

(for those not familiar with lambda, the code right of the arrow is just a singular method body, so it just calls that one singular piece of code).
image

(my implementation of movement, called in Update() )
image

(EDIT 1: conditional logic to switch control schemes)

Thirdly,

After getting the Gameobjects and Script setup, go back to your gameobjects once again, and dropdown the Unity Events section, and then one more dropdown of whatever you called your Action Map. You should see a “movement” Event depending on what you named it, press the plus button, and drag the movement script on the gameobject you’re currently on, down or over to the field where it says “None (object)” and it should load up with the script. Click on the dropdown, and navigate over towards your script class name, find your Movement method, and assign it. Do the same for the other gameobject, as its alright if they share the same script as long as the movement is setup in a mostly modular fashion.

(First Player or one of the players)

(Second Player or one of the other players)

With that it should be working! Let me know if any issues arise and I’ll try to look into them but after poking around on forums and with videos telling me nothing, this seemed to work pretty well.