Search Unity

[Solved] Two PlayerInputs

Discussion in 'Input System' started by alkaitagi, Oct 17, 2019.

  1. alkaitagi

    alkaitagi

    Joined:
    Dec 8, 2016
    Posts:
    87
    I have two quite independent game objects in one scene: Player and Manager. They work in parallel and read completely different inputs. I tried creating two InputActions assets and assigning them into two PlayerInput components (one for Player and Manager), but only single of those components work. So apparently multiple PlayerInputs is not an option.

    One way of solving this problem I was thinking about is having ActionMap on a component where I will enable and disable it with the component and manually read values each update. But it is inconvenient to have a somewhat big group of actions being stored and edited inside the component, and not in a dedicated asset as it is with InputActions asset.
     
  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    PlayerInput automatically takes care of duplicating actions. Assign the same action asset to one, then duplicate it and you have two players.

    Note that by default each player receives a unique set of devices. So if player 1 grabs everything and there's nothing left for player 2, the latter one will not see any input coming through.

    Use control schemes to separate different means of controlling your game and prevent PlayerInput from assigning more devices than necessary to a single player.

    Use PlayerInput.Instantiate to explicitly pair devices to players.

    USe PlayerInputManager to have a lobby where players join explicitly through devices.
     
    viesc123 likes this.
  3. alkaitagi

    alkaitagi

    Joined:
    Dec 8, 2016
    Posts:
    87
    @Rene-Damm

    I have assigned two InputAction assets to two PlayerInput components. Now I can see in the debug section that one component has Keyboard&Mouse devices and the other PlayerInput has nothing. So there is no way keyboard and mouse can be used by two PlayerInputs simultaneously?

    Or is there another way how I can execute and read values from two different action maps stored as assets?
     
    Last edited: Oct 17, 2019
  4. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    The same control scheme can be used by arbitrary many players but not the same devices, by default.

    To have two players use the same device, you need to manually instantiate the players with those devices or pair the devices manually to the player's InputUsers.

    Code (CSharp):
    1. // Create two players both using the same keyboard and mouse.
    2. PlayerInput.Instantiate(playerPrefab, controlScheme: "Keyboard&Mouse", devices: new[] { Keyboard.current, Mouse.current });
    3. PlayerInput.Instantiate(playerPrefab, controlScheme: "Keyboard&Mouse", devices: new[] { Keyboard.current, Mouse.current });
     
    viesc123 likes this.
  5. alkaitagi

    alkaitagi

    Joined:
    Dec 8, 2016
    Posts:
    87
    Thank you very much, I have finally understood.

    I have created extension class:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public static class InputInitializer
    5. {
    6.     public static PlayerInput Initialize(this PlayerInput input)
    7.     {
    8.         var instance = PlayerInput.Instantiate(input.gameObject, controlScheme: "Keyboard&Mouse", pairWithDevices: new InputDevice[] { Keyboard.current, Mouse.current });
    9.  
    10.         instance.transform.parent = input.transform.parent;
    11.         instance.transform.position = input.transform.position;
    12.  
    13.         Object.Destroy(input.gameObject);
    14.         return instance;
    15.     }
    16. }
    17.  
    Which I call like this:
    Code (CSharp):
    1.  
    2. private void Awake()
    3. {
    4.     input = GetComponentInChildren<PlayerInput>().Initialize();
    5. }
    6.  
    With object hierarchy like this ("Input" object has PlayerInput component):
    upload_2019-10-18_15-7-48.png
     
  6. alkaitagi

    alkaitagi

    Joined:
    Dec 8, 2016
    Posts:
    87
    @Rene-Damm Although it would be nice to have a built-in option to "force" players to pair with selected devices.
     
  7. MamieDev

    MamieDev

    Joined:
    Nov 7, 2020
    Posts:
    2
    Sorry for up this topic (and for my bad english), but i don't understand all what you did @alkaitagi
    In my case, i try to use left stick on my gamepad to moving my player, and the right stick to rotate the camera, which is in an other GO (and i can't just place my camera in the player). So here is my questions :
    - Where did you write this lines, on which script ?
    - what is your "input" variable in the awake function and how it is work exactly ?

    Thanks for the time
     
  8. alkaitagi

    alkaitagi

    Joined:
    Dec 8, 2016
    Posts:
    87
    @SebYnoV I did exactly what Rene showed - instantiated & binded a player input runtime. I suppose you would need to instantiate 2 input components as well, for the Player and for the Camera. `InputInitializer` is a static class, you can take it as is and it might help you. The second code block, the `awake()` function, just called the static class to create an input instance, which I saved in a local variable in my Player script for subsequent use.
     
  9. katecobey

    katecobey

    Joined:
    Jul 11, 2022
    Posts:
    10
    Hey! This should theoretically work, but it won't let me attach the extension class as a script ?
     
  10. katecobey

    katecobey

    Joined:
    Jul 11, 2022
    Posts:
    10
    Okay so if I put it in the script where I'm initializing everything, what it's doing instead is initializing my object indefinitely, over and over again, even though it should only run once with awake. :| I've figured out that what's going on is essentially that it creates a new object, and then that object runs the script... indefinitely. It also only returns a clone object which is throwing all my other scripts off.
     
    Last edited: Jul 12, 2022
    devramyun likes this.
  11. tv_Never

    tv_Never

    Joined:
    Nov 11, 2021
    Posts:
    11
    I'm having the same issue with the second player having no input devices. I have the players instantiated through another script so I can't instantiate via the playerinput.instantiate. Is there another way for the second player to get all the devices?
     
  12. Pnvanol

    Pnvanol

    Joined:
    Jan 11, 2016
    Posts:
    122
    So what the function PlayerInput.Instantiate do exactly? , it doesnt seem to instantiate the prefab
    I am calling
    PlayerInput.Instantiate(animalCompanion, 1, "Gamepad1", -1, new[] { Gamepad.all[1] });
    Do I need the animalCompanion on the scene already with a player.input component on it?

    Edit:Nevermind I had an error that was preventing the instantiation gamepad.all had only one value

    How do I get the spawned player to be used by the second gamepad?

    Ok I found the solution thank you for the original comment
     
    Last edited: Aug 3, 2023