OnSerializeNetworkView, please help!

Hello!

So I’ll get straight to the point, my goal for script is for the client to try and change its spriteID, send the request to the server which then changes the actual spriteID. Then. through OnSerializeNetworkView I seek to update the sprite on all clients on the network.

The other example in OnSerializeNetworkView shares the updated transform to all clients when a client has moved and is working as intended, BUT.

My question is, why doesn’t the second example dealing with sprite updates not work properly?
The server changes the sprite, but all OnSerializeNetworkView seems to do in terms of updating the clients is to update the spriteID on the NetworkPlayer who sent the request exclusively and not to everybody else. What is the source and the solution of this issue?

Thank you in advance. :slight_smile:

	void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
	{

		if(stream.isWriting)
		{
			print("Is Writing" + info.sender + info.networkView);

			Vector3 pos = transform.position;
			stream.Serialize (ref pos);

			int id = 0;
			id = sprite.spriteId;
			stream.Serialize(ref id);
		}
		else if(stream.isReading)
		{
			print("Is Receiving");

			Vector3 posReceive = Vector3.zero;
			stream.Serialize(ref posReceive);
			transform.position = Vector3.Lerp (transform.position, posReceive, 0.9f);

			int idReceive = 0;
			stream.Serialize(ref idReceive);
			sprite.spriteId = idReceive;
		}
	}
}

Here’s the full script:

using UnityEngine;
using System.Collections;

public class playerMoveAuthoritative : MonoBehaviour 
{
	public NetworkPlayer theOwner;
	float lastClientHInput = 0f;
	float lastClientVInput = 0f;
	Vector2 lastClientInput = Vector2.zero;
	float serverCurrentHInput = 0f;
	float serverCurrentVInput = 0f;

	tk2dBaseSprite sprite;
	Vector3 moveDirection = Vector3.zero;

	int clientSpriteID = 0;
	int serverSpriteID = 0;

	NetworkViewID viewID;

	void Start()
	{
		sprite = GetComponent<tk2dBaseSprite>();

	}
	void Awake()
	{
		if (Network.isClient)
			enabled = false;

	}

	[RPC]
	void SetPlayer(NetworkPlayer player)
	{
		theOwner = player;
		if(player == Network.player)
			enabled = true;
	}

	void Update()
	{
		viewID = Network.AllocateViewID();

		if(theOwner != null  Network.player == theOwner)
		{
			float HInput = Input.GetAxis ("Horizontal");
			float VInput = Input.GetAxis ("Vertical");
			if(Input.GetKeyDown (KeyCode.A))
			{
				clientSpriteID = 3;
			}
			if(Input.GetKeyDown (KeyCode.S))
			{
				clientSpriteID = 2;
			}
			if(Input.GetKeyDown (KeyCode.D))
			{
				clientSpriteID = 1;
			}
			if(Input.GetKeyDown (KeyCode.W))
			{
				clientSpriteID = 0;
			}


			if(lastClientHInput != HInput || lastClientVInput != VInput)
			{
				lastClientHInput = HInput;
				lastClientVInput = VInput;
				if(Network.isServer)
				{
					SendMovementInput(HInput, VInput);
					SendPlayerOrientation(viewID, clientSpriteID);
				}
				else if(Network.isClient)
				{
					networkView.RPC ("SendMovementInput", RPCMode.Server, HInput, VInput);
					networkView.RPC ("SendPlayerOrientation", RPCMode.Server, viewID, clientSpriteID);
				}
			}
		}

		if(Network.isServer)
		{
			moveDirection = new Vector3(serverCurrentHInput, serverCurrentVInput, 0);
			float speed = 3f;
			transform.Translate (speed * moveDirection * Time.deltaTime);

			sprite.spriteId = serverSpriteID;
		}

	}

	[RPC]
	void SendPlayerOrientation(NetworkViewID viewID, int clientSpriteID)
	{
		serverSpriteID = clientSpriteID;
	}


	[RPC]
	void SendMovementInput(float HInput, float VInput)
	{
		serverCurrentHInput = HInput;
		serverCurrentVInput = VInput;
	}

	void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
	{

		if(stream.isWriting)
		{
			print("Is Writing" + info.sender + info.networkView);

			Vector3 pos = transform.position;
			stream.Serialize (ref pos);

			int id = 0;
			id = sprite.spriteId;
			stream.Serialize(ref id);
		}
		else if(stream.isReading)
		{
			print("Is Receiving");

			Vector3 posReceive = Vector3.zero;
			stream.Serialize(ref posReceive);
			transform.position = Vector3.Lerp (transform.position, posReceive, 0.9f);

			int idReceive = 0;
			stream.Serialize(ref idReceive);
			sprite.spriteId = idReceive;
		}
	}
}

Your not sending the update to the server from the client.
Only locally your changing the id.
If you look at the movement code, your sending your movement data to the server using RPC’s.
But you aren’t doing that for the sprite id’s

I thought I was sending the update to the server from the client through this line:

networkView.RPC ("SendPlayerOrientation", RPCMode.Server, viewID, clientSpriteID);

Could you propose a solution?

Ah yes, I didn’t think setrotation was the one handling the id’s.
Yes you are sending the id’s.
Try to debug what happens on the remote end.

int idReceive = 0;
stream.Serialize(ref idReceive);
Debug.Log(idReceive);
sprite.spriteId = idReceive;

Unity doesn’t seem to want to print anything from OnSerializeNetworkView’s isReading condition, only from isWriting. Does this mean that nothing is reading from the NetworkView, and everything is writing? The server is the one who spawned the objects carrying the NetworkViews in my case, which I believe means that it is the owner of all the NetworkViews (isWriting). This leaves none to account for the non-owners(ie. There are no readers).
Does that make any sense?

However, this doesn’t account for the fact that the change in position for one client is updated on all clients. And it doesn’t explain why the client who sent the request can see itself change the sprite, and the server can see all correct sprite-changes as they happen. If I comment out either of the lines in isReading/isWriting, not even the client who sent the request can see any updates, which leads me to think that it’s doing something, just not what I expected/wanted.

It’s worth mentioning that tk2dBaseSprite.spriteId (ie. sprite.spriteId) is derived from a plugin, and isn’t part of the Unity base package.