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

Keyboard Splitter (Local Multiplayer Keyboard)

Discussion in 'Input System' started by Fenrisul, Apr 22, 2020.

  1. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Hey all, wanted to share this with everyone!

    I wrote a utility that creates virtual keyboards and shuffles events around to make PlayerInput/PlayerInputManager think there are more devices and made it really easy to remap keys.

    Attached unitypackage to this post.

     

    Attached Files:

  2. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    @Rene-Damm

    If you would sir :)

    Take a peek at the code here - its pretty obvious my keypresses will probably be "One frame late" using this method.
    Is there a way to create new StateEvents and have them processed immediately? Calling InputSystem.Update() at the end of an event callback seems like a bad idea heh.
     
  3. Esile01

    Esile01

    Joined:
    Jun 6, 2019
    Posts:
    1
    Hi, thank you so much for your script, happy to have this solution !
    I just have errors (NullReferenceExceptions) when using it, it seems very low level related
    upload_2020-5-2_16-3-37.png
    Any idea? Is this really caused by your script or have I done something wrong on my side?
     
  4. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Hmm, what version of Unity and InputPackage do you have?
     
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Yeah, there's a couple other pieces of code that are confronted with the same problem. ATM it's not possible to queue input events from within input event processing and have the events flushed out in the same cycle. Only events queued from within onBeforeUpdate will make it into the same frame.

    What you *can* do, however, is bypass event processing through InputState.Change. This will still trigger action monitors and process the state change in a controlled way but it allows to basically jam state changes directly and immediately into the system.

    Code (CSharp):
    1. InputState.Change(Keyboard.current, new KeyboardState(Key.A));
     
    ProceduralCatMaker likes this.
  6. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    Hi @Fenrisul thank you for your solution it will really help us debug & playtest our game when no controllers are around.

    I can't seem to get a second keyboard player set up properly. I followed the instructions in the video but only the first player config is working (ie, it works with the default keyboard controls as well as if I remap the controls of player 1) but player to is never recognized (irregardless of remapping it or not).

    Using InputSystem 1.0.0 and tried it on my scene and also the Simple Multiplayer sample that comes with InputSystem. No luck. Any help is appreciated!
     
  7. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    I seem to have gotten it working. My control scheme had both "Keyboard" and "Mouse" in the required devices (as did the Simple Multiplayer sample). Removing "Mouse" fixed the issue and the utility works as expected now. Thanks!
     
  8. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    @Fenrisul I see that the script only works with the "Join Players When Button Is Pressed" option on PlayerInputManager. When selecting "Join Players When Join Action Is Triggered" and given a reference it works once (accepting the Join Action from either layout) but not from the second layout that attempts to join.
    Any easy workaround for this that you can think of?
     
  9. stanferrolino12

    stanferrolino12

    Joined:
    Sep 8, 2020
    Posts:
    1
    The script works, I think.
    The splitter now feeds output to both of the joined players, which I think is because I implemented my input into my player by making an instance of the input asset and getting my input from there.
    Code (CSharp):
    1. void Awake()
    2.     {
    3.        
    4.         BodyController = GetComponent<BodyController>();
    5.         Controls = new PlayerControls();
    6.     }
    7.  
    8.     private void OnEnable() { Controls.Enable(); }
    9.  
    10.     private void OnDisable() { Controls.Disable(); }
    11.  
    12. void ManageInput()
    13.     {
    14.         InputVector.x = Controls.Player.Movement.ReadValue<Vector2>().x;
    15.     }
    16.  
    any workarounds to this?
     
  10. Marythu

    Marythu

    Joined:
    Mar 29, 2021
    Posts:
    13
    Hey @Fenrisul ,

    great Video! I was searching for weeks and couldnt find a working solution, but i feel your script is the closest i can get. Just like shown in the video i added the keyboard splitter component and i am (finally) able to spawn a second player (with the keyboard), but they both move in sync all the time. When i use the right half of my keyboard both players follow the same instructions and when i use the left half its the same. Do you know any solution to the problem?

    Thanks in advance!
     
  11. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Hi! I've attached a package with an Example of this script working correctly. If the example scene fails the same way, I can help you figure out what's going on.
     

    Attached Files:

  12. Marythu

    Marythu

    Joined:
    Mar 29, 2021
    Posts:
    13
    I cant believe it o_O Your scene is perfectly working and i cant find anything that i did different. Maybe you could take a quick look at my scene, because i am not experienced enaugh to find the solution. Of course i understand if you dont want to, but it would be a huge help, because im struggling for weeks now. If not i can start a new project from the bottom with the new input system done first.
     
    Last edited: Jun 11, 2021
  13. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    I see you're using the Generate C# Class option. The Unity PlayerInputManager and PlayerInput class are not compatible with Generate C# Class.

    See the example I posted and how its using the SendMessages option of PlayerInput to marshal the controls to the player's instanced prefab.

    Additionally I actually made a few tutorials on "How to get goin" with this stuff:
    https://forum.unity.com/threads/best-practices-getting-started-tutorials.875818/
    The local multiplayer one in particular is probably of interest to ya.

    There are definitely more interesting ways to deal with local-multiplayer since I wrote that tutorial, but this should at least get ya started.
     
  14. Marythu

    Marythu

    Joined:
    Mar 29, 2021
    Posts:
    13
    Ohhh. Thank you so much! I finally got it! I just assumed the Generate C# Class is needed after i saw it in another tutorial. Great tutorial and thanks again for your help!
     
  15. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    You're welcome! :)

    And yea... it would be nice if Unity shipped an Input System with 3 modes of use that were all compatible with eachother... but they didn't, and its a sad state of affairs.
     
    ModLunar and Marythu like this.
  16. wolfenswan

    wolfenswan

    Joined:
    Nov 4, 2020
    Posts:
    3
    First up: great job, really appreciate your effort.

    However, I'm currently running into a very odd bug that's tricky to pin down, as I'm not getting any error messages.

    Essentially the splitter works great... until it does not. It seems that it stops working after I have modified some code in my scripts and Unity has re-compiles. Not always, but if the issue occurs, it's after re-compiling.

    Likewise I can't reliably get it get to work again. Dis/re-enabling the KeySplitter component does not seem to work. Again, letting C# re-compile after modifying *anything* in my project does sometimes seem to help, as does a restart of the entire project. As before, it's not reliable solution.

    As you can probably tell by that terrible bug report I'm completely stumped :) Open to any ideas to help pin this one down.
     
    Last edited: Apr 30, 2021
  17. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Indeed horrible bug report! lol.

    What version of Unity, Input System, and which path are you using? (Generate C# Class, PlayerInput, manually linking Actions, etc).
     
  18. wolfenswan

    wolfenswan

    Joined:
    Nov 4, 2020
    Posts:
    3
    2020.3.1f1, Input System 1.0.2

    I've got a fairly standard setup: Player Input Manager set to "join when button is pressed", the PlayerInput invokes Unity Events, which are then intercepted by my PlayerController which sets the movement etc.

    I'll add more debug.logs to determine at what point the splitter fails (or if the issue occurs earlier, pointing towards another cuprit)
     
  19. MCKoleman

    MCKoleman

    Joined:
    Oct 17, 2019
    Posts:
    3
    This script is exactly what I've needed for a long time! Unfortunately, I'm running into a weird issue where when attempting to join players by input the input system does not recognize the input until around 5 to 10 seconds have passed in the runtime, after which the system works flawlessly. If you have any ideas what could be causing it I'd appreciate the help.
     
  20. bome99

    bome99

    Joined:
    Sep 14, 2009
    Posts:
    119
    This is just what I was looking for!
     
  21. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    I have the same issue. Looks like the longer the editor is open, the longer it takes to "freeze" the input for 5-10 seconds. I hope @Fenrisul releases a fix for this soon!
     
  22. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    What version of Unity and InputSystem are you using?
     
  23. S1L3nCe

    S1L3nCe

    Joined:
    Aug 18, 2019
    Posts:
    2
    @Fenrisul Same delay issue at start here with 2021.2.8f1 and 1.2.0 with your example package.
    Thanks for your work anyway :)
     
  24. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Attached what I think is a fix. I was passing UnityEngine.Time, but now cache the time an originating event was generated and then re-inject. That variable initial lag time is the difference between InputSystem's double precision time, and UnityEngine.Time - which could appear as a negative number depending on init order.

    Let me know if that resolves it for you please!
     

    Attached Files:

  25. S1L3nCe

    S1L3nCe

    Joined:
    Aug 18, 2019
    Posts:
    2
    It's indeed now working as expected, no more inputs lags at start.
    Thank you!
     
    Last edited: May 3, 2022
  26. HDZD

    HDZD

    Joined:
    Aug 3, 2013
    Posts:
    2
    Hey @Fenrisul
    Package works great but when I do a scene reload I get the following error:
    upload_2022-2-26_0-38-51.png

    From what I understand Keyboard.current is returning null, though I do have keyboard added in the input system package supported devices list (which is the only fix I could find after googling that problem specifically).

    and I can no longer join with more than 1 player on keyboard, any idea what might be going on?
     
    Last edited: Feb 25, 2022
  27. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    Thanks so much for fixing this!

    I updated to Unity 2021LTS this week and it looks like KeyboardSplitter is broken (inspector is behaving weird and second keyboard player is not connecting )

    I hope you have the time to update it. Your work is much appreciated :)
     
  28. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Oof at 2021LTS breaking stuff - I'll take a look when I can! I haven't moved up yet myself.
     
  29. amirblum

    amirblum

    Joined:
    Jan 24, 2014
    Posts:
    14
    I know - if only Unity's Input System handled this classic use case!

    That being said, it actually appears to be working for me now. I didn't change anything, but I did have some controllers connected at the time, so that might have affected it.

    The inspector is still buggy (attaching a pic) but the second keyboard player DOES connect and work so no pressure from my end :D

    upload_2022-6-19_22-30-52.png
     

    Attached Files:

  30. IbrahimRashwan

    IbrahimRashwan

    Joined:
    Oct 21, 2018
    Posts:
    4
    You really saved me a lot of headaches, Thank you very much.
     
  31. katecobey

    katecobey

    Joined:
    Jul 11, 2022
    Posts:
    10
    Hey, I was recommended this-- my use case involves two separate prefabs. Any tips for this?
     
  32. bvandriel

    bvandriel

    Joined:
    Dec 14, 2020
    Posts:
    1
    THANKS!!!! Had to look for a while where to remove 'Mouse' from the Control Scheme, but found it. Leaving this screenshot for others who are looking for this solution:

    upload_2023-1-8_21-54-14.png

    Note that I also renamed the Scheme, from 'Keyboard&Mouse' to 'Keyboard'. Pressing 'minus' here kills all mouse input to the Player.
     
    Last edited: Jan 8, 2023
  33. bmo22

    bmo22

    Joined:
    Apr 12, 2023
    Posts:
    1
    @Fenrisul A similar thing is hapenning to me. When I save a script or do any change that causes Unity to recompile stuff while running the game, I get the following error:

    InvalidOperationException: Invalid user
    UnityEngine.InputSystem.Users.InputUser.get_index () (at Library/PackageCache/com.unity.inputsystem@1.4.4/InputSystem/Plugins/Users/InputUser.cs:86)
    UnityEngine.InputSystem.Users.InputUser.UnpairDevices () (at Library/PackageCache/com.unity.inputsystem@1.4.4/InputSystem/Plugins/Users/InputUser.cs:629)
    UnityEngine.InputSystem.Users.InputUser.UnpairDevicesAndRemoveUser () (at Library/PackageCache/com.unity.inputsystem@1.4.4/InputSystem/Plugins/Users/InputUser.cs:689)
    KeyboardSplitter.OnDestroy () (at Assets/Scripts/Player/KeyboardSplitter/InputSystem/Scripts/KeyboardSplitter.cs:167

    After this, I can no longer join with more than 1 player on keyboard until I restart the Unity editor.

    Unity version: 2021.3.16f1
     
    Last edited: Apr 14, 2023