- Home /
Multiple NetworkBehaviours with the same SyncVar hook not working
This is going to be a lot of text, scroll down to
I'm trying to place 2 of the same of the same script onto a single object.
PlayerPrefab scripts/behaviours
The script is set up to sync the position/rotation/networktimestamp of the "Transform Sync". Here I'm using the basic FirstPersonController renamed PlayerPrefab and the camera renamed PlayerCamera. There is also a capsule on it and an object attached to the camera so that I can see where they are and so that I can see the rotation of the PlayerPrefab and the PlayerCamera
PlayerPrefab in the editor
Here's what it looks like in the inspector. The Capsule and the LocalRotationPositionArms are just meshes with no colliders, no funny business on them.
So the script I wrote should sync the Transform of the PlayerPrefab itself, and also sync the Transform of the PlayerCamera object.
The Problem
It appears only one script, the later script, is being given information. Both scripts are working side by side for the clients connecting to the host. The functionality I tried to implement falls apart.
Code
The code I have looks like this. A single instance of the script appears to work fine for me.
StringNetworkBehaviour
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public abstract class StringNetworkBehaviour : NetworkBehaviour {
[SyncVar (hook = "SyncMessage")]
private string Message = string.Empty;
protected StringSerializable MessageModel { get; set; }
protected virtual void FixedUpdate()
{
this.TransmitMessage ();
}
public virtual bool TransmitCondition()
{
return this.isLocalPlayer;
}
public virtual StringSerializable GetStringSerializable()
{
return this.MessageModel;
}
public virtual void SendNext(StringSerializable messageModel)
{
this.MessageModel = messageModel;
}
public string GetLastRecievedMessage(){
return this.Message;
}
[Command]
protected virtual void Cmd_TrasmitMessageFromClientToServer(string message)
{
this.Message = message;
}
[ClientCallback]
protected virtual void TransmitMessage()
{
if(this.TransmitCondition())
{
StringSerializable message = this.GetStringSerializable();
if(message != null)
{
this.Cmd_TrasmitMessageFromClientToServer(message.SerializeToString());
}
}
}
[Client]
protected virtual void SyncMessage(string message)
{
this.Message = message;
}
}
StringSerializable
using UnityEngine;
using System.Collections;
public interface StringSerializable {
string SerializeToString();
void DeSerializeFromString(string serialized);
}
NetworkSyncPositionRotation
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[NetworkSettings (channel = 0, sendInterval = 0.1f)]
public class NetworkSyncPositionRotation : StringNetworkBehaviour {
[Tooltip("This transform will be synced. Defaults to the object's tranform.")]
public Transform TransformSync;
[Tooltip("Each time the position and rotation are Lerped, the amount it lerps will be this percentage towards the target.")]
public float LerpRate = 10f;
[Tooltip("If set to true, the local position and rotation will be synced instead of the world position and rotation.")]
public bool UseLocalPositionAndRotation = false;
void Awake()
{
if (this.TransformSync == null) {
this.TransformSync = this.transform;
}
}
void Update ()
{
if (this.isLocalPlayer)
{
int time = NetworkTransport.GetNetworkTimestamp ();
StringSerializable message = null;
if(!this.UseLocalPositionAndRotation)
{
message = new PositionRotationMessageModel (this.TransformSync.position, this.TransformSync.rotation, time);
} else {
message = new PositionRotationMessageModel (this.TransformSync.localPosition, this.TransformSync.localRotation, time);
}
this.SendNext (message);
}
else
{
this.LerpPositionRotation ();
}
}
void LerpPositionRotation()
{
if (!string.IsNullOrEmpty (message))
{
var model = PositionRotationMessageModel.BuildFrom(message);
if(!this.UseLocalPositionAndRotation)
{
this.TransformSync.position = Vector3.Lerp (this.TransformSync.position, model.Position, LerpRate * Time.deltaTime);
this.TransformSync.rotation = Quaternion.Lerp (this.TransformSync.rotation, model.Rotation, LerpRate * Time.deltaTime);
}
else
{
this.TransformSync.localPosition = Vector3.Lerp (this.TransformSync.localPosition, model.Position, LerpRate * Time.deltaTime);
this.TransformSync.localRotation = Quaternion.Lerp (this.TransformSync.localRotation, model.Rotation, LerpRate * Time.deltaTime);
}
}
}
public override bool TransmitCondition()
{
return this.isLocalPlayer;
}
}
PositionRotationMessageModel
using UnityEngine;
using System.Collections;
public class PositionRotationMessageModel : StringSerializable
{
public Vector3 Position {get;set;}
public Quaternion Rotation {get;set;}
public int TimeStamp {get;set;}
public PositionRotationMessageModel()
{
}
public PositionRotationMessageModel(Vector3 pos, Quaternion rot, int timeStamp)
{
this.Position = pos;
this.Rotation = rot;
this.TimeStamp = timeStamp;
}
public static PositionRotationMessageModel BuildFrom(string serialized)
{
var obj = new PositionRotationMessageModel ();
obj.DeSerializeFromString (serialized);
return obj;
}
public string SerializeToString()
{
string message = string.Empty;
message += this.Position.x + "\t" + this.Position.y + "\t" + this.Position.z;
message += "\t";
message += this.Rotation.x + "\t" + this.Rotation.y + "\t" + this.Rotation.z + "\t" + this.Rotation.w;
message += "\t";
message += this.TimeStamp;
return message;
}
public void DeSerializeFromString(string serialized)
{
string[] split = serialized.Split ('\t');
this.Position = new Vector3 (float.Parse (split [0]), float.Parse (split [1]), float.Parse (split [2]));
this.Rotation = new Quaternion (float.Parse (split [3]), float.Parse (split [4]), float.Parse (split [5]), float.Parse (split [6]));
this.TimeStamp = int.Parse(split [7]);
}
}
NetworkSetupPlayerControl
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class NetworkSetupPlayerControl : NetworkBehaviour
{
[Tooltip("The camera that this player object controls.")]
public Camera PlayerCamera;
[Tooltip("The audio listener that this player object controls.")]
public AudioListener PlayerAudioListener;
public override void OnStartLocalPlayer ()
{
GameObject.Find("Scene Camera").SetActive(false);
this.PlayerCamera.enabled = true;
this.PlayerAudioListener.enabled = true;
this.GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>().enabled = true;
this.transform.position = new Vector3 (0, 3, 0);
}
}
The general idea is that I wanted to make a simple way to send lots of information using a string. The problem is that placing two of my NetworkSyncPositionRotation scripts on the same object seems to break it. I'm concerned that if I extend anything else off of StringNetworkBehaviour that it'll also break, since I believe it's breaking at the hook.
My goal was to create a simple to extend way to deal with Unity's networking so I wouldn't have to write too much to create my scripts. That's why all the syncing logic is in StringNetworkBehaviour and my NetworkSyncPositionRotation just builds and serializes a message and sets it to be sent then forgets about it.
Question
Is the behaviour that's breaking my script intentional? Or am I overlooking something? Can it be fixed?
Notes
The behaviour seems to function perfectly as I intended for the client who is Hosting locally. All the clients can see the host perfectly as he is supposed to be displayed. The host and the clients see all the non hosts as messed up. Not sure why that's going on.
Commenting to add that I'm receiving the exact same issue with a similar Transform-syncing script,
For now I'm using the Unity NetworkTransform / NetworkTransformChild combo ins$$anonymous$$d for the time being, where looking into the Child's scripting here seems like an index is needed in the network message transmitting the sync values?
Answer by Ferur · Aug 29, 2015 at 01:56 PM
hi, i am not 100% sure, but i don't think the virtual FixedUpdate() is ever called from Unity because its not in the derived class, so you never actually Transmit the message. I guess because the host is using the same scene for the server and the local client changing the message there is enough to get it onto the server and it gets sent to the clients through the syncVar.
FixedUpdate is being called from the class StringNetworkBehaviour
Yes, FixedUpdate is in StringNetworkBehaviour, but you only use the derived class on your Gameobject. I havent tested it myself, thats why i said i am not 100% sure, but in this thread the answer from Peter $$anonymous$$ suggests that Unity will not call FixedUpdate if its only in the base class. So reimplementing the method in your derived class might fix it.
Your answer
Follow this Question
Related Questions
Can I see how many bytes are being sent by a particular SyncVar variable? 1 Answer
Two or more players in tank using mirror 1 Answer
This is giving an error for the other client and cannot hit other client. 1 Answer
Can I use Rpc Calls and Commands on the same object? 0 Answers
Remote database for leaderboard 2 Answers