Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Multiple players on Keyboard (New Input system)

Discussion in 'Input System' started by luycaslima, Aug 11, 2019.

  1. luycaslima

    luycaslima

    Joined:
    Jul 22, 2018
    Posts:
    1
    Hello,
    I'm trying to make a local multiplayer on the keyboard.
    I made it work with the joysticks to create a new player when pressed a button, but on the keyboard the manager only see as only one player. How do I set some buttons to activate one player and other buttons to another one?

    Example:
    Player 1 : WASD
    Player 2 : Arrows
     
  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Hotseat setups require some custom scripting as by default, PlayerInput will not assign the same device to more than one player. One way to work around that is by manually spawning the player prefabs

    Code (CSharp):
    1. player1 = PlayerInput.Instantiate(playerPrefab, controlScheme: "Arrows", pairWithDevice: Keyboard.current);
    2. player2 = PlayerInput.Instantiate(playerPrefab, controlScheme: "WASD", pairWithDevice: Keyboard.current);
    Unfortunately, it's not yet possible to override PlayerInputManager's prefab spawning to do that on-the-fly from the joining logic but that bit should be there by 1.0.
     
    Paraave and clayton_axel like this.
  3. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    @Rene-Damm Hey :) any update on this?

    I have a player, and a main camera.
    I'm using 2 InputActionAssets, 1 contains the controls for the player, and 1 contains the controls for the camera.

    Though to be fair, maybe I'm using the system incorrectly?

    EDIT: Nevermind, my "SendMessage"s were not being called cause my Actions were named with spaces in them!
     
    Last edited: Jan 21, 2020
  4. bobbaluba

    bobbaluba

    Joined:
    Feb 27, 2013
    Posts:
    81
    Just ran into this today... Is it still the plan to have it in 1.0? (we're at 1.0.0 preview.6 now)
     
    ModLunar likes this.
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Addressing this unfortunately didn't make it for 1.0. However, we're getting pretty close to cutting 1.0 final after which we'll spend some time addressing the list of smaller needed improvements that have accumulated by now.
     
    ModLunar likes this.
  6. GTG101

    GTG101

    Joined:
    Feb 1, 2017
    Posts:
    24
    I tried this and it gave this error:

    The best overload for 'Instantiate' does not have a parameter named 'controlScheme' [Assembly-CSharp]csharp(CS1739)

    Is there a new way of doing this?
     
  7. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
  8. GTG101

    GTG101

    Joined:
    Feb 1, 2017
    Posts:
    24
    That's an interesting script Fenrisul, but if the line of code would work it'd be a way simpler solution.
     
  9. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    You need zero lines of code if you set it up with my script :) It treats it like there are 2 keyboards, and no changes made to the InputActionMap.
     
  10. Angelo13C

    Angelo13C

    Joined:
    Feb 16, 2020
    Posts:
    11
    It doesn't work, when I instantiate my player using PlayerInput.Instantiate(), if I Debug.Log(playerInput.devices[0]), it is correct.. But then my player loses the device, in the inspector I can see my PlayerInput script that has no device

    Code (CSharp):
    1. PlayerInput playerInput = PlayerInput.Instantiate(_playerInputPrefab, pairWithDevice: Keyboard.current);
    2.             playerInput.SwitchCurrentActionMap("Player 2");
     
    itzaelcasanova42 likes this.
  11. ll3v3ll

    ll3v3ll

    Joined:
    Nov 14, 2014
    Posts:
    11
    It seems using the default Joining mechanism will not allow Joining from the same device, once the Device is paired.
    If the Device (the Keyboard) is paired, Joining is halted.
    If the Device (the Keyboard) is not already paired, Joining proceeds.

    ((com.unity.inputsystem@1.0.0-preview.7\InputSystem\Plugins\Users\InputUser.cs))

    A potential solution to this would involve changing / enhancing / the system so that Joining will check for and pair a more fine grained combination of "Device:ControlScheme" such as "Keyboard:KeyboardLeft" and "Keyboard:KeyboardRight", etc.

    --

    Additionally, when one device is split into two Control Schemes
    [i.e. KeyboardLeft (WASD,Tab,Space) and KeyboardRight (Arrows, Enter, Bs)]

    The Player Join() method will assign the first ControlScheme (like KeyboardLeft) to the device, even though the joining control has come from a SPECIFIC Control Scheme (from KeyboardRight or KeyboardLeft).
    The joined player control scheme (on PlayerInput) will always be the first control scheme.

    --
     
  12. nullwaresoft

    nullwaresoft

    Joined:
    Jan 7, 2020
    Posts:
    18
    Hello! Neither playerInput.Instantiate nor playerInput.SwitchCurrentActionMap seem to be working for me. This simple line would solve a huge trouble I'm going through, could you give me a little help here? :)
     
  13. IceTrooper

    IceTrooper

    Joined:
    Jul 19, 2015
    Posts:
    35
    Any news @Rene-Damm about supporting multiple players on the same keyboard natively by Input System?

    or we got the only solution with custom call to JoinPlayer API? It's not bad, but it would be nice to see that solution at least in 'How to...' section in docs, because I think there are many users who don't know how to setup up this manually.
     
    Last edited: Mar 15, 2021
    ModLunar likes this.
  14. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    This is why I wrote my Keyboard Splitter that treats the Keyboard as 2 (or more) virtual keyboards and thus Users if used with the player joining API's - doesn't get much simpler than that.
     
  15. lordmigit

    lordmigit

    Joined:
    Jan 18, 2019
    Posts:
    1
    @Rene-Damm do you know if this feature will ever be included in the new input system?
     
  16. Shaolin-Dave

    Shaolin-Dave

    Joined:
    Apr 3, 2015
    Posts:
    32
    I'm currently trying to just get multiple GameObjects to access the same keyboard/gamepad in a single-player game.

    I have player controls, ie "move", "jump", and "shoot". For this I have an InputAction on my Player object.

    I also have the system controls to "start", "pause", "unpause", and "quit" the game. For this I have an InputAction on my GameManager object. I've tried both the same InputAction, or two different ones accepting the same input device.

    I mean, you should be able to hit ESC to pause and W to move forward on the same keyboard, right?

    Unfortunately it appears that Unity recognizes the first (only) keyboard I have connected to my computer as either the GameManager or Player one, and doesn't allow me to do the other.
     
  17. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Pasting one of my answers from above:
    https://forum.unity.com/threads/keyboard-splitter-local-multiplayer-keyboard.874135/

    I wrote this to intercept keyboard stuff and make Unity think there are 2 or more virtual keyboards.
     
  18. Shaolin-Dave

    Shaolin-Dave

    Joined:
    Apr 3, 2015
    Posts:
    32
    That might work for some instances, but what about when there's gamepads, or a mixture? What if it's more than two gameobjects needing the same input, will you need 10 virtual keyboards/gamepads for each potential player?

    Seems like a better goal would be to have the same device be assigned to two objects, rather than fooling Unity into thinking there's more than one of them.
     
  19. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Two objects needing the same input would share the same PlayerInput, thats fine - just spawn your PlayerInput as an invisible object and distribute events or values from it. It's bad practice to instantiate and register a device to an object you are gonna destroy unless you want the user to press a Join Button to keep playing, but even then you risk losing the physical player's link to that device(or virtual device).

    Are the users switching between parts of the keyboard or exchanging gamepads during play? o_O

    The general idea is you would define as many Virtual Keyboards as you can fit Physical Players on a single keyboard. A single gamepad would be interchangeable with a single Virtual Keyboard.

    If you want to reserve Escape as a universal Pause Button thats fine too! I would actually go the route of treating that as a special case rather than a user define-able key in the case of keyboard-sharing; you can subscribe to events without using Actions at all, or even poll the Keyboard.current[Key.Escape] values.

    The gist of it PlayerInput is designed to hold "One or more devices for a Physical User"; that's just how its built. Sharing a single device between Physical Users requires some concessions, and my Keyboard Splitter is designed to make it more seamless.

    *ninja edit*
    Also worth mentioning that you are under *no* obligation to use PlayerInput at all, but it does have a decent framework for associating physical users to devices.
     
  20. pet_Cz

    pet_Cz

    Joined:
    Jan 17, 2014
    Posts:
    9
    Is this working now? Or did I missed something? I just try to make two default Input Actions; from the first one, I've deleted WASD, and from the second one arrows. I have 2 GO each with their own Player Input and Input Actions and a common script that reacts to OnMove. Everything seems to work correctly. One GO is controlled by arrows, the second one by WASD. But from the discussion above, I feel it should not work.
     
    Thygrrr likes this.
  21. tapiovalli

    tapiovalli

    Joined:
    Jul 26, 2018
    Posts:
    11
    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 :

    Code (CSharp):
    1. public class GameObjectController : MonoBehaviour
    2. {
    3.  
    4.     public InputActionAsset inputActionsAsset;
    5.  
    6. ....
    7.  
    8.  
    9.   void Start()
    10.     {
    11.  
    12.         inputActionsAsset.Enable();
    13.  
    14.         InputAction move = inputActionsAsset.FindAction("Move");
    15.  
    16.         move.started += OnStart;
    17.         move.canceled += OnStart;
    18.  
    19. ...
    20.  
    21.   private void OnStart(InputAction.CallbackContext context)
    22.     {
    23.         isStarted = true;
    24.     }
    25.  
    26.  
    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
     
    Last edited: Sep 4, 2021
  22. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    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
    PlayerInput
    s from being able to "claim" it. The way around this is to either manually spawn
    PlayerInput
    s as in my post way up there or to force
    PlayerInput
    s onto a device after the fact.

    Code (CSharp):
    1. PlayerInput.all[0].SwitchCurrentControlScheme("KeyboardWASD", Keyboard.current);
    2. PlayerInput.all[1].SwitchCurrentControlScheme("KeyboardArrows", Keyboard.current);
     
    Last edited: Sep 7, 2021
    noio, tapiovalli and ModLunar like this.
  23. Paraave

    Paraave

    Joined:
    Sep 28, 2020
    Posts:
    2
    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:

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

    gabagpereira

    Joined:
    Jan 21, 2019
    Posts:
    23
    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:
    Code (CSharp):
    1. var player = PlayerInput.Instantiate(_playerPrefab, controlScheme: controlScheme, pairWithDevice: device);
    2. player.SwitchCurrentControlScheme(controlScheme, device);
     
  25. katecobey

    katecobey

    Joined:
    Jul 11, 2022
    Posts:
    10
    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?
     
  26. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    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.
     
    Brodus likes this.
  27. tylerkealy

    tylerkealy

    Joined:
    Oct 8, 2018
    Posts:
    5
    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...
     
  28. JauntyBearGames

    JauntyBearGames

    Joined:
    Mar 26, 2018
    Posts:
    57