How to create a lightweight remote avatar?

Options
We are a VR game with a single remote opponent, and would like to have our opponents represented by a simple avatar, rather than the complex character prefab.

We're struggling with how to sync the data between 2 different classes/prefabs. We tried manually setting the viewId to match, but OnPhotonSerializeView never gets called.

Any tips?

Comments

  • TreeFortress
    edited October 2016
    Options
    Yay, I think I basically solved it.

    1. Attach a PhotonView to both your mainPlayer and remoteAvatar objects.
    2. Created a shared component to handle serialization, which you can attach to your mainPlayer, and remoteAvatar. It can read/write the necessary variables for your AvatarScript to read:
    public class NetworkedPlayerSerializer : MonoBehaviour, IPunObservable
    {
        public Vector3 NetPos { get; set; }
        public Quaternion NetRot { get; set; }
    
        public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
            if (stream.isWriting) {
                stream.SendNext(transform.position);
                stream.SendNext(transform.rotation);
            }
            else {
                NetPos = (Vector3)stream.ReceiveNext();
                NetRot = (Quaternion)stream.ReceiveNext();
            }
        }
    }
    
    3. Your AvatarScript can now look at the Serializer component, and update itself to match.
    public class NetworkedAvatar : BetterPunBehavior
    {
        NetworkedPlayerSerializer playerSerializer;
        
        void Update() {
            var t = Time.deltaTime * 5;
            transform.position = Vector3.Lerp(transform.position, playerSerializer.NetPos, t);
            transform.rotation = Quaternion.Lerp(transform.rotation, playerSerializer.NetRot, t);
        }
    4. The tricky part is getting them talking. After joining a room, using AllocateViewId() to assign a VIEW_ID to your mainPlayer's photonView.
    int viewId = PhotonNetwork.AllocateViewID();
    localPlayer.photonView.viewID = viewId;
    
    5. Broadcast a buffered RPC to other players, telling them to create an Avatar, with said VIEW_ID (or simply enable an existing Avatar gameObject in their local scene, and assign the VIEW_ID if they want to avoid any instantiation)
    public class NetworkedPlayerSerializer : MonoBehaviour, IPunObservable
    photonView.RPC("RPC_ShowAvatar", PhotonTargets.OthersBuffered, viewId);
    
    You must broadcast this RPC from an existing PhotonView that exists on all clients. We just added one to our main LobbyManager.

    Now the two objects will now stay in sync, despite not sharing anything other than that small component. They do not have to be instantiated over the network either, simply by existing in the scene and having the proper viewId assigned the objects can talk.