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
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
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.
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.
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.
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 csharp** **if(!IsOwner) { stickmanAnimations.CheckForEmote(myAnimator); } CheckForEmoteClientRpc();** ** and this csharp** **if(!IsOwner) { stickmanAnimations.CheckForEmote(myAnimator); CheckForEmoteClientRpc(); }** **
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.
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.
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.
Just make another script named as “ClientNetworkAnimator” and paste the following code in it, and after pasting and saving the code, remove the NetworkAnimator script from your player object and put this script in it, then put your player object’s animator in the “animator” of “ClientNetworkAnimator”. Save the scene, test it out, it works fine.
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode.Components;
using UnityEngine;
public class ClientNetworkAnimator : NetworkAnimator
{
protected override bool OnIsServerAuthoritative()
{
return false;
}
}