Search Unity

Client Animations not displaying on the host

Discussion in 'Netcode for GameObjects' started by JustLabbing, May 10, 2022.

  1. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6
    Hey, so currently I've been trying to learn about Unity Multiplayer Services like Relay, Lobby, and Netcode for GameObjects. Everything has been going fine so far until recently I ran into a issue with the Network Animator and getting client animations to work on host.

    Here is a video showing what I mean


    So basically the system behind it is very simple, There are several keys a player can press. Depending on the key they press, an emote animation will play. This is done by
    Code (CSharp):
    1.  public void PerformEmote(Emotes emoteUsed, Animator myAnimator)
    2.     {
    3.         if(Input.GetKeyDown(emoteUsed.inputRequired))
    4.         {
    5.             myAnimator.Play(emoteUsed.animationClip.name, -1, 0);
    6.         }
    7.     }
    The stickman object has a Network Object, the player script on the object inherits from network behavior, has a client network transform and Network Animator on it.
    The movement system works fine and is reflected on both the host an client but its just animations currently.

    I having trouble understanding why the client's animation is not running on the host. I'm still thinking of possible solutions

    Is it because of the way I'm playing the animation? Ex.) myAnimator.Play()
    Is it because of I need a ServerRPC call to perform it on host version of the client's model?


    I'm still spit balling here. Has anyone ran into this problem before and how should I go about fixing this issue.
    If find the answer, I'll add it here for anyone in future who has this problem
     
  2. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    The NetworkAnimator is server authoritative only. So unlike the ClientNetworkTransform you need to make changes on the server. As you mentioned you can use a ServerRpc call to perform the animation on the host and that will correctly replicate it to all the clients.
     
    JustLabbing likes this.
  3. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6
    Thanks for the help. After trying new approach, I tried to perform a ServerRPC from client but I get no animation on the client and when I try it on the host, both the client and client host wave.

    Here is the code setup for performing action
    Code (CSharp):
    1. void Update()
    2.     {
    3.         if(canMove)
    4.         {
    5.             if (IsOwner)
    6.             {
    7.                 Move();
    8.                 if (!IsHost)
    9.                 {
    10.                     CheckForEmoteServerRpc();
    11.                    
    12.                 }
    13.                 else if (IsServer)
    14.                 {
    15.                     stickmanAnimations.CheckForEmote(myAnimator);
    16.                 }
    17.             }
    18.          
    19.         }
    20.     }
    21.  
    22.     [ServerRpc(RequireOwnership = false)]
    23.     void CheckForEmoteServerRpc()
    24.     {
    25.         stickmanAnimations.CheckForEmote(myAnimator);
    26.         //CheckForEmoteClientRpc();
    27.         Debug.Log("Client Wave");
    28.     }
    29.     [ClientRpc]
    30.     void CheckForEmoteClientRpc()
    31.     {
    32.         stickmanAnimations.CheckForEmote(myAnimator);
    33.         Debug.Log("Client Wave");
    34.     }
    Is this the right way to approach?

    The prevoius verison from video was like this
    Code (CSharp):
    1.  void Update()
    2.     {
    3.         if(canMove)
    4.         {
    5.             if (IsOwner)
    6.             {
    7.                 Move();
    8.                 stickmanAnimations.CheckForEmote(myAnimator);
    9.             }
    10.          
    11.         }
    12.     }
     
  4. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    Checking for a key press should still happen on the client. Calling an animation if the right key is pressed should happen on the server.

    It might however be better to remove the NetworkAnimator if the player is client-authorative and just replicate all animations of the local player on the other clients via ServerRpc+ClientRpc. That way, the player never experiences a delay with their own animations. The flow would then be (assuming PlayEmote() is the function name):

    Update: check for key press -> if pressed call PlayEmote(), then PlayEmoteServerRpc() -> in PlayEmoteServerRpc(), call PlayEmote() if not the owner and then call PlayEmoteClientRpc() -> in PlayEmoteClientRpc(), call PlayEmote() if not the owner and not the server.
     
    JustLabbing likes this.
  5. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6
    Thanks for the info, I adjust the code accordingly but it seems to make them both perform the emote when I press a key for an emote.

    In the video, I tried both with and without the network animator and got the following results.
    • With Network animator host animations were playing on client but client animations not playing on host
    • Without Network animator, host animations were not showing on client and client animations weren't playing on host
    I'm sure i'm doing something wrong on my part. I'm still trying stuff and reviewing the documentation on RPC.

    Edit
    On that ServerRPC call, I didn't notice a difference between this
    Code (CSharp):
    1. if(!IsOwner)
    2.         {
    3.             stickmanAnimations.CheckForEmote(myAnimator);
    4.         }
    5.         CheckForEmoteClientRpc();
    and this
    Code (CSharp):
    1. if(!IsOwner)
    2.         {
    3.             stickmanAnimations.CheckForEmote(myAnimator);
    4.             CheckForEmoteClientRpc();
    5.         }


    StickmanAnimations.png PlayerController.png
     
    Last edited: May 11, 2022
  6. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    You are still checking for key presses on all clients/server, in your CheckForEmote function. Only call this function locally, in the Update loop, for IsOwner (or IsLocalPlayer). Then if an animation should be played, use a ServerRpc to play it if there is a NetworkAnimator, or a ServerRpc+ClientRpcs if there is not as I suggested above.

    As to your edit: you don't notice a difference because ClientRpcs can only be called by the server.
     
    JustLabbing likes this.
  7. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6
    Thanks for letting me know

    Code (CSharp):
    1. // Update is called once per frame
    2.     void Update()
    3.     {
    4.         if(canMove)
    5.         {
    6.             if (IsOwner)
    7.             {
    8.                 Move();
    9.              
    10.             }
    11.             if (IsLocalPlayer)
    12.             {
    13.                 if (Input.anyKeyDown)
    14.                 {
    15.                     stickmanAnimations.CheckForEmote(myAnimator);
    16.                     CheckForEmoteServerRpc();
    17.                 }
    18.             }
    19.          
    20.         }
    21.     }
    22.  
    23.     [ServerRpc(RequireOwnership = false)]
    24.     void CheckForEmoteServerRpc(ServerRpcParams serverRpcParams = default)
    25.     {
    26.         if(!IsOwner)
    27.             stickmanAnimations.CheckForEmote(myAnimator);
    28.         CheckForEmoteClientRpc();
    29.     }
    30.     [ClientRpc]
    31.     void CheckForEmoteClientRpc(ClientRpcParams clientRpcParams = default)
    32.     {
    33.         if (!IsOwner && !IsServer)
    34.             stickmanAnimations.CheckForEmote(myAnimator);
    35.         Debug.Log("Hit " + IsLocalPlayer);
    36.     }
    I've made the changes but now I'm back at the beginning where Host animations are playing on client but client animations are not playing on host.


    I checked out this video on Netcode Animations and they don't seem to run into this problem.
     
  8. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    You're still doing what I repeatedly said was the problem: don't have ServerRpcs or ClientRpcs to *check* for emotes (i.e. key presses), only have them to *play* the emotes.
     
    JustLabbing likes this.
  9. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6
    So just so I'm clear on this,

    You are saying that since CheckForEmote Function is in another class (outside of RPC), it won't be excuted.

    So I should just move logic from that function into the Sever and Client RPC and it should work.

    CheckForEmote is actually doing the perform emote. I should just put this together and place in my RPC right?
    Code (CSharp):
    1.  public void PerformEmote(Emotes emoteUsed, Animator myAnimator)
    2.     {
    3.         if(Input.GetKeyDown(emoteUsed.inputRequired))
    4.         {
    5.             myAnimator.Play(emoteUsed.animationClip.name, -1, 0);
    6.         }
    7.     }
    8.  
    9.     public void CheckForEmote(Animator myAnimator)
    10.     {
    11.         if(Input.anyKeyDown)
    12.         {
    13.             myEmotes.ForEach(ele =>
    14.             {
    15.                 if(Input.GetKeyDown(ele.inputRequired))
    16.                 {
    17.                     PerformEmote(ele, myAnimator);
    18.                 }
    19.  
    20.             });
    21.         }
    22.     }
     
  10. JustLabbing

    JustLabbing

    Joined:
    Sep 25, 2019
    Posts:
    6


    That was the fix, So at the end.

    The issue I was having was that in the Server and Client RPC.

    You have to do your actions there and not go into any other functions outside of your Network Behaviour. I was using "stickmanAnimations.CheckForEmote(myAnimator);" when I had to break it down even further and have everything that was inside of CheckForEmote and put inside of the RPC.

    Thanks for all your help getting through this problem. I'll learned a lot and couldn't have done it with out you.

    :)
     
    Last edited: May 12, 2022
    langqing429 likes this.
  11. prathamarora333

    prathamarora333

    Joined:
    Jun 13, 2020
    Posts:
    1
    Hey can you please share your solution as I am having the same issue and i am unable to understand the solution.
     
  12. ertbaran

    ertbaran

    Joined:
    Feb 22, 2019
    Posts:
    11
    My solution was:
    DONE!