Sync Players Animations (Legacy)

Hi again, it's Ohiyx4. I'm trying to sync players animations/Input over the network. I'm using Legacy animations so I cant use the Animator. The first way I tried was to send the local currently playing animation as a string over a RPC Buffered, so every other player can get the string. The problem was I didnt know how I could play the animation on the sender gameobject other than the receiver and also I dont want to send a RPC every frame to detect Input.
Luckily, I got closer to solving my problem by having a look at Vikings demo and how they sync their animations. I used character states and then serialized it using OnPhotonSerializeView just like in the ThirdPersonNetwork script.
It works half way, I can see other players playing their Idle animations while they are Idle, but when they are moving the Idle animation is still playing and I can't see their Walking animation. I'm pretty sure it must be a easy fix to this.
Have a look:
PlayerNetwork.cs
using UnityEngine;
using System.Collections;

public enum CharacterStates
{
	Idle = 0,
	Walking = 1,
	Swim = 2,
}
public class PlayerNetwork : Photon.MonoBehaviour
{
	public Vector3 cam;
	public bool isControllable = false;
	public bool swim;
	
	public CharacterStates _characterState;
	
	private Vector3 correctPlayerPos = Vector3.zero; //We lerp towards this
    private Quaternion correctPlayerRot = Quaternion.identity; //We lerp towards this
	
    void Awake()
    {
		swim = GetComponent<CharacterInputController>().Swim;
		PhotonNetwork.isMessageQueueRunning = true;
		
		if(photonView.isMine)
		{  	
        
		this.GetComponent<CharacterMotor>().enabled = true;
		this.GetComponent<Builder>().enabled = true;
		this.GetComponent<CharacterInputController>().enabled = true;
		this.GetComponent<MouseLook>().enabled = true;
		this.GetComponentInChildren<Camera>().enabled = true;
		this.GetComponent<GameGUI>().enabled = true;
		this.GetComponent<GameStateManager>().enabled = true;
		this.GetComponent<InventoryGUI>().enabled = true;
		//this.GetComponent<PauseGUI>().enabled = true;
		this.GetComponentInChildren<MouseLook1>().enabled = true;
		this.GetComponentInChildren<PhotonCycle>().enabled = true;
		
		cam = this.GetComponentInChildren<Camera>().transform.position;
			
		}
		else 
		{
		this.GetComponent<CharacterMotor>().enabled = false;
		this.GetComponent<Builder>().enabled = false;
		this.GetComponent<CharacterInputController>().enabled =false;
		this.GetComponent<MouseLook>().enabled = false;
		this.GetComponentInChildren<Camera>().enabled = false;
		this.GetComponent<GameGUI>().enabled = false;
		this.GetComponent<GameStateManager>().enabled = false;
		this.GetComponent<InventoryGUI>().enabled = false;
		this.GetComponentInChildren<PhotonCycle>().enabled = false;
		//this.GetComponent<PauseGUI>().enabled = false;
		this.GetComponentInChildren<MouseLook1>().enabled = false;
		
		}
		
	}

void Update()
    {
		swim = GetComponent<CharacterInputController>().Swim;
		
		if(isControllable == true){
			if(Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
			{
				_characterState = CharacterStates.Walking;
			}
			else {
				_characterState = CharacterStates.Idle;
			}
			if(swim == true){
				_characterState = CharacterStates.Swim;
			}
		}
		
		if(_characterState == CharacterStates.Idle){
			animation.Play("Idle");
		}
		if(_characterState == CharacterStates.Walking){
			animation.Play("Walk");
		}
		if(_characterState == CharacterStates.Swim){
			animation.Play("Swim");
		}
		Debug.Log(_characterState + " " + isControllable);
	}
	
 void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting)
        {
            //We own this player: send the others our data
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation); 
			
			Camera myA = GetComponentInChildren<Camera>();
			stream.SendNext((Camera) myA);
			
			PlayerNetwork myC = GetComponent<PlayerNetwork>();
			stream.SendNext((int)myC._characterState);
			
        }
        else
        {
            //Network player, receive data
            correctPlayerPos = (Vector3)stream.ReceiveNext();
            correctPlayerRot = (Quaternion)stream.ReceiveNext();
						
            Camera myA = GetComponentInChildren<Camera>();
            myA = (Camera) stream.ReceiveNext();
			
            PlayerNetwork myC = GetComponent<PlayerNetwork>();
            myC._characterState = (CharacterStates)stream.ReceiveNext();
			
        }
    }

}
isControllable is set using OnJoinedRoom() in another script like this:
public void OnJoinedRoom()
	{
		
		GameObject myPlayer = (GameObject) PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0, 150, 0), Quaternion.identity, 0);
			myPlayer.name = myPlayer.name + photonView.viewID;
			cam = myPlayer.GetComponent<PlayerNetwork>().cam;
			myPlayer.GetComponent<PlayerNetwork>().isControllable = true;
		
	}
PlayerNetwork.cs is on the root of the Instantiated gameobject with the Animation Component and is always active. Thanks for the help!

Comments

  • I can't debug your code actually but maybe some tips will help.
    You should check if the states of your local character are actually arriving in the way you expect. Also double-check where you set the state of remote characters. They should not change the state unless they stop moving or something, which should be an incoming message from outside.

    Don't buffer the RPCs. They are outdated within no time. Everyone who is in the room gets the "live" updates anyways. Joining players should just wait a moment until everyone sent an update.