Input System Local Multiplayer Without InputManager

How do we do local multiplayer with the new input system, if we do not want to use the InputManager?

The architecture of my game with the old input system was, a script called PlayerInput.cs which would look at each PlayerMovement script, and based on which integer was assigned to it, it would configure those mappings to it. Ex:

if (playerNum == 1)
        {
            if (xBox)
            {
                //print("PLAYER: " + playerNum + " = 1 xbox - " + gameObject.name);
                playerMovementRef.aButton = "X_P1_A";
                playerMovementRef.leftStickX = "X_P1_LeftStick_X";
                playerMovementRef.leftStickZ = "X_P1_LeftStick_Z";
                playerMovementRef.bButton = "X_P1_B";

Is something similar achievable in the new system? I’m just not sure on how to configure which controller belongs to which player.

One way is to simply manage PlayerInput instances yourself. You can, for example, just instantiate them directly using PlayerInput.Instantiate.

You can put all the bindings in the .inputactions asset and group them using control schemes. E.g. have an “Xbox” control scheme that requires an XInput controller. The equivalent code to the snippet you posted would then look something like this

if (playerNum == 1)
{
    if (xbox)
        PlayerInput.Instantiate(playerPrefab, controlScheme: "xbox");

If you have control schemes and you don’t give specific devices to the player (like in the above code), it will simply go looking for what it needs in the global list of devices (InputSystem.devices). So the above code would simply grab the first XInput gamepad available.

Thanks for the response Rene-Damm! Is this an acceptable way of programming local multiplayer with the new input system, or would you suggest a different way? The reason I ask is because I have different prefabs for different players that would get instantiated so the InputManager won’t work for me.

Absolutely.

What I’m trying to do now is this:

playerInput = PlayerInput.Instantiate(this.gameObject, controlScheme: "Xbox");

        // Instantiate new input system
        playerControls_p1 = new PlayerControls_P1();
        playerControls_p1.Player_OnFoot.EastButton.performed += ctx => EastButtonPerformed();
        playerControls_p1.Player_OnFoot.EastButton.canceled += ctx => EastButtonCanceled();

I’m instantiating the PlayerInput on the gameObject that I want to use it. And then binding the methods to the events.
This is causing Unity to crash and it’s the instantiate line. Your previous explanations are very helpful and it’s making much more sense now, but there’s something else I’m not understanding.

You mean, there’s an exception? What it’s the console?

Unity just crashes and I have to Force Quit.

To be completely accurate, Unity stops responding.

Sounds like an infinite loop. Be aware that the Instantiate line will run the full gamut of component Awake/OnEnable/Start methods so if those happen to trigger the same codepath again, boom.

I added a bool to only run through this line once but it crashed again which leads me to believe that PlayerInput.Instantiate is not instantiating the PlayerInput component on the gameobject (that we pass in), but instantiating the actual gameobject itself. Which would cause an infinite loop. Is this correct?

All of the last post has been corrected. I’m instantiating 2 players into the scene and each of them are getting input from both controllers. Would my next step be to loop through the gamepads and pass one into PlayerInput.Instantiate?

Instantiate() will automatically grab them if none are passed to it. To pass them explicitly, add them to the Instantiate() call.

Thanks Rene-Damm, I’m sorry for so much back and forth. I think I may have discovered the issue. I’m using the Events console for the controller and when I’m pressing a button on either controller it’s coming up as Device 12 for both. Then when I press a button on the other controller nothing registers. The device id is 0 for each frame.
Is it possible that there is an issue with my drives/unity where everything is getting recognized as the same device?

7445840--913040--Screen Shot 2021-08-24 at 3.02.43 PM.png

Apologies, let me explain that better. In the Input Debug under the devices select I see 2 xbox controllers.
When I open up the first one to see the input coming in, I see input coming in from a button pressed on either controller. When I open up the second one to see the input coming in, I see no input coming in from either controller.
Have you encountered anything like this before? I see that both virtual controllers exist, but each physical controller only gives input to the first controller on the list.

Which platform? Is this happening with Xbox controllers on Mac?

Sorry for the late reply. Yes, this is happening with Xbox controllers on Mac.

Hey Rene-Damm, how do you think I should proceed with this? Are any other users experiencing this?
I’m using Big Sur OS.

Ticket through the Unity bug reporter with as much details as possible would be appreciated. This sounds like something that might need some looking at on our end.

Will do, thanks for all of your help!