Search Unity

Resolved MLAPI with New Input System -> Clients have the wrong "Actions" in "Player Input" component

Discussion in 'Multiplayer' started by edin97, Jan 31, 2022.

  1. edin97

    edin97

    Joined:
    Aug 9, 2021
    Posts:
    58
    Hello, I'm learning networking with Netcode for gameobjects (MLAPI 1.0.0-pre.4), I'm also using the new input system (1.3.0), so my Player Prefab has the "Player Input" component with my own "Input Action Asset" under the "Actions" variable. The issue is, the Host player has the correct Actions, but the clients have a cloned version of it, which doesn't exist.

    Example : my Input Action Asset is called "GameControls". The (NetworkObject) player prefab has the correct "GameControls". The host has his correct "GameControls" under Actions. But, the clients joining have "GameControls(Clone)" under Actions which doesn't exist. -> see picture below

    The thing is, I CAN change it MANUALLY while the game is running for each players and give them the right "GameControls" and it works but I think this is just a bug ? Or am I missing something ?
     

    Attached Files:

  2. edin97

    edin97

    Joined:
    Aug 9, 2021
    Posts:
    58
    Workaround I'm using for now :

    Code (CSharp):
    1.  
    2. public class AttachCorrectInputs : NetworkBehaviour
    3. {
    4. // Get "Player Input" component which sould be attached to player prefab
    5. private PlayerInput playerInput;
    6. // Assign correct InputActionAsset in the player's prefab inspector
    7. [SerializeField] private InputActionAsset inputActionAsset;
    8.  
    9.     private void Start()
    10.     {
    11.         // Get "Player Input" component when Player is initialized
    12.         playerInput = gameObject.GetComponent<PlayerInput>();
    13.     }
    14.  
    15.    // On spawn
    16.    public override void OnNetworkSpawn()
    17.    {
    18.         base.OnNetworkSpawn();
    19.         // Make sure this belongs to us
    20.         if (!IsOwner) { return; }
    21.         // check if we have the wrong inputActionAsset
    22.         if (playerInput.actions != inputActionAsset)
    23.         {
    24.             // if we have the wrong one, we assign the correct one
    25.             playerInput.actions = inputActionAsset;
    26.         }
    27.    }
    28. }
    Add this C# code to your player's prefab and then go to the player's prefab inspector and add your correct inputActionAsset in the variable field, (mine is "GameControls" from the picture in the original post)

    Edit (for people who have multiple ActionMaps) : so, I have multiple "Action Maps" in my InputActionAsset. I thought this workaround didn't work for vector2 but my vector2 values are on my 3rd Action Map which I forgot to enable. So, I enabled it and now everything works. But, I still think the (cloned) is a bug/error. Here is what I added to enable my 3rd ActionMap at the end of the OnNetworkSpawn() method : "playerInput.actions.FindActionMap("Moving").Enable();" since it's only relevant to me, I won't update the worakaround code, but be aware that your need to enable other action maps
     
    Last edited: Feb 1, 2022
    PabloIH and mateuszwallace like this.
  3. PabloIH

    PabloIH

    Joined:
    Sep 20, 2014
    Posts:
    12
    Amazing thanks! This worked for me
     
  4. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hi @edin97 , thanks for flagging this. I forwarded the issue to the Netcode for Gameobjects ("NGO") team, which tried to replicate it by adding a scriptable object to a networked object and spawn it. Unfortunately everything seems to go fine when they do it, so the issue is probably somewhere else.

    Since this could be a really nasty bug and we really want to fix it, would you be able to provide a project to reproduce it? Alternatively, could you try upgrading to the latest NGO version (1.1.0), remove your workaround, and see if the issue persist?

    Thank you in advance!
     
  5. edin97

    edin97

    Joined:
    Aug 9, 2021
    Posts:
    58
    Hello @RikuTheFuffs-U, thanks for reaching out ! So, since then, I found that the real issue was not the InputActionAsset component, it is the playerInput component. In fact, I haven't read the whole Netcode or NewInput documentation, so this whole issue might be my fault for not searching more infos. But, what I found is that you need the playerInput component to be disabled on the GameObjects that are not yours (or maybe : only 1 playerInput should be enabled at the same time in the scene for a multiplayer game (?)). For example : as a client, I need to disable the playerInput component from the server and other clients which I don't own/use. So, what I do now is the following: I disable the playerInput component on the player's prefab, then on the workaround I wrote above, I replace this part :

    Code (CSharp):
    1.         if (playerInput.actions != inputActionAsset)
    2.         {
    3.             // if we have the wrong one, we assign the correct one
    4.             playerInput.actions = inputActionAsset;
    5.         }
    by :
    Code (CSharp):
    1.         playerInput.enabled = true;
    (also line 7 can be removed)

    since we have "if (!IsOwner) { return; }" one line above ; only the player's owner is enabling the playerInput component. -> now you only have 1 playerInput enabled in your scene. The reason the first workaround worked is probably because the playerInput script sends the input to the most recent component (?)

    So, maybe there is a segment in the documentation that is talking about this, but I might have missed it, and I apologize for that. If this is not the expected behavior, I can still provide the whole project, since I have it for some reason. I did upgrade to NGO (1.1.0), the workaround is still needed for the inputs to work. When workaround is disabled, at runtime : on clients-side which can't move, you can manually disable the playerInput on each player that is not yours. And then on your own player, you disable then re-enable the playerInput and you will be able to move on both client and server side.

    This is probably the expected behavior, but it feels counter intuitive for beginners, in my opinion. Maybe an auto-disable all playerInput component on GameObjects instantiated that are not yours option (toggle option for NetworkManager script?) would be cool or idk some warning in the documentation if there is none.
     
    Pandazole and jairneto55 like this.
  6. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    @edin97 Thank you for the detailed reply, and happy to see that you managed to solve the issue!
    Yes, in general you should only have one player input script/system active on clients (the one of the local player). Your solutions is what I'd have done as well. The same would apply to all other systems that send input on behalf of the player.

    I agree that it might be confusing. I'll bring this feedback to the doc team to see if we can add some example code on how to manage the situation you came across. Maybe that'll help other people in your situation!
     
    Pandazole and edin97 like this.
  7. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    edin97 and CladInRed like this.