- Home /
UNet SyncVar not working
Hello,
I have spent the last couple of weeks learning about the UNet API and have all my movement scripts working perfectly, but I am having a problem with getting my item script working properly.
The way I thought I needed it to work is as follows:
Object triggers collider TriggerEvent
TriggerEvent sends a command to the server
Server calls a RPC on all clients which changes the value of a synced variable.
The active boolean is does not change though.
public class Item : NetworkBehaviour {
[SyncVar]
public bool active = true;
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
PickupItem(other.gameObject);
}
}
public virtual void PickupItem(GameObject player)
{
CmdDisable ();
}
[Command]
private void CmdDisable()
{
active = false;
RpcDisable ();
}
[ClientRpc]
private void RpcDisable()
{
active = false;
}
}
Answer by n1gth · Jul 16, 2015 at 08:40 AM
You don't need to change the variable on the client. The SyncVar changes automatically on the client when it is changed on the server. Your setup looks correct for this to happen - you perhaps should add Debug calls to ensure that the collider is working correctly.
If you want, you could add a hook on the client.
[SyncVar(hook = "OnActiveChange")]
private bool active = false;
Then when the value changes on the server, the hook is called on the client (which then takes responsibility for setting the value on the client).
private void OnActiveChange(bool updatedActive)
{
active = updatedActive;
Debug.Log("Active changed on client: "+active);
}
Thanks for point out my mistake. I modified my code to fit what you suggested but OnActiveChange is not being called. The trigger is working.
public class Item : NetworkBehaviour {
[SyncVar(hook="OnActiveChange")]
public bool active = true;
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
print("Triggered");
PickupItem(other.gameObject);
}
}
public virtual void PickupItem(GameObject player)
{
CmdDisable ();
}
[Command]
private void CmdDisable()
{
active = false;
}
private void OnActiveChange(bool updatedActive)
{
active = updatedActive;
Debug.Log ("Active changed on client!");
}
}
What you have looks correct. Are you on the latest patch version of unity? Have you started the game through the Network$$anonymous$$anager?
I am using 5.1.0f3. I am starting the game using the Network$$anonymous$$anager HUD component.
You could try using the latest patch, I know several syncvar issues were fixed. It's 5.1.1p4.
I updated to the latest patch but that did not solve the problem. I also added a check to see if it was the local player because of a warning which was generated.
public virtual void PickupItem(GameObject player)
{
if(isLocalPlayer)
CmdDisable ();
}
Also here is the class which is extending the base Item class.
public class ItemHealth : Item {
[SerializeField] float healAmount = 25f;
public override void PickupItem (GameObject player)
{
//player.GetComponent<Player_Health> ().Heal (healAmount);
base.PickupItem (player);
}
}
Answer by Clemens-Scharfen · Jul 27, 2015 at 11:05 AM
Is it possible that you are trying to change your syncVar in the editor / inspector? As far as I have figured it out, you cannot make your syncVar changes in the inspector. At least for me, it only worked when I changed a synced variable by script.
[SyncVar]
private bool active = true;
[Server] // Might also happen in a Command
private void OnlyCalledOnServer()
{
// Change the syncVar by script, should affect server and client(s):
active = false;
}
I think, it works for n1gth because he uses a private variable and changes it in his code. So his answer is pretty fine, I guess. (By the way, the UNET Manual uses only private syncVars in its examples too.)
I am not sure if it is a bug or not, that it is not possible to change public syncVars in the editor. At least it is a little bit annoying because you cannot test it by changing the variable in the inspector, also not if you are using a private variable with the [SerializeField] Attribute additionally to the [SyncVar] Attribute. That is my experience with Unity 5.1.2 so far.
yes, the editor bypasses the accessor properties used by SyncVars when values are changed in the inspector, so SyncVar dirty flags are not set when changes are made in the editor :(
Answer by chanyow · Feb 28, 2017 at 01:57 PM
you need to add your script on the player which has the networkIdentity.