How to make multiple player inputs work using the same device?

My InputActions asset is setup like this using 2 control schemes “KeyboardP1” and “KeyboardP2”:


Then I have a PlayerInputLogger prefab with a PlayerInput component using my PlayerInputActions asset and my PlayerInputLogger component:

Here’s the code for PlayerInputLogger component:

public class PlayerInputsLogger : MonoBehaviour {
    public InputActionReference Action1;
    
    void Start() {
        Action1.action.performed += _ => Debug.Log("Action 1 performed");
    }
}

Then, I have PlayerInputsSpawner object and the component in the test scene. Here’s the code for PlayerInputsSpawner component:

public class PlayerInputsSpawner : MonoBehaviour {
    public GameObject PlayerInputLogger;

    void Start() {
        PlayerInput Player1 = PlayerInput.Instantiate(PlayerInputLogger, controlScheme: "KeyboardP1", pairWithDevice: Keyboard.current);
        PlayerInput Player2 = PlayerInput.Instantiate(PlayerInputLogger, controlScheme: "KeyboardP2", pairWithDevice: Keyboard.current);
    }
}

When I start the game, here’s how the scene looks like:

It logs only when I press on the G key and not Numpad1 key. When I switch the control schemes on the spawned objects, so that the first instantiated object uses KeyboardP2 control scheme, it logs when I press numpad1 key but not the G key. Only the first instantiated object is working.

I’m trying to do it this way, because it was recommended to do it this way in those threads: 2 Players on same input device
Multiple players on Keyboard (New Input system) - #25 by katecobey

But it doesn’t work. Any advice?

I just reproduced your setup (I did not use numpad keys) and it worked for me, the only other possible difference is that I deleted all other control schemes (which shouldn’t have an impact necessarily), could you try if you have the same problems not using the numpad - I assume it is related to numpad usage?

1 Like

Thank you for your answer.
I worked around it and used a different solution that worked.
I switched to not use InputActionReference, and instead I generated a C# class from PlayerInputActions asset, then instantiated it in my own component, then set the PlayerInputActions on the PlayerInput component. Here’s my component:

public class PlayerActionsReporter : MonoBehaviour {
    public PlayerInput PlayerInput;
    public PlayerInputActions PlayerInputActions;

    void Awake() {
        PlayerInputActions = new PlayerInputActions();
        PlayerInput.actions = PlayerInputActions.asset;
        PlayerInput.user.AssociateActionsWithUser(PlayerInputActions);
        PlayerInput.SwitchCurrentControlScheme(PlayerInput.defaultControlScheme, Keyboard.current);
    }
}

And then from PlayerController I subscribe to the events of PlayerInputActions variable:

        Action1 = PlayerActionsReporter.PlayerInputActions.ActionMap.Action1;

        Action1.performed += _ => CurrentCharacter.Action1.Begin();
        Action1.canceled += _ => CurrentCharacter.Action1.End();

This works and I like this solution even better than the one with InputActionReference: it’s nice and type safe, the hierarchy of original input actions is preserved and it automatically updates, and I don’t have to drug InputActions in the editor, so it’s less error-prone I’d say.

1 Like