Network synchronization doesn't work on client side.
I tried the Unity Tutorial on how to set up a basic network. I have made my way through it but I stumble on the synchronization of the health variable.
If I press Q the following code will be executed:
TakeDamage(100);
CmdFire ();
Wherein TakeDamage is (CMD fire kills all players aroud it for exception the caster):
public void TakeDamage(int amount)
{
if (!isServer)
{
return;
}
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
dead = true;
GetComponent<Animator> ().SetBool ("Dead", dead);
GetComponent<NetworkAnimator>().SetTrigger("Dead");
}
}
If I use this on the host side everything works fine and both players die and will have the healthbar set to 0. But if I try this on the clientside the player that presses Q (the only player on the client and not the host) will live and the other player will die. This is both the case for the host and the client.
Here is my full code:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour
{
private Rigidbody rb;
private Animator anim;
[SyncVar]
public bool dead;
public float groundCheckDistance = 1f;
public GameObject explosion;
public Vector3 spawnLoc = new Vector3(0, 1, 0);
public float moveSpeedForwards;
public float moveSpeedSideways;
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public override void OnStartLocalPlayer()
{
//gameObject.GetComponent<NetworkAnimator>().SetParameterAutoSend(0,true);
// Set the main camera of a local player to the camera position of the player prefab
var camera = Camera.main;
//camera.parent = gameObject.GetComponent ("CamPos").transform;
camera.transform.SetParent(gameObject.transform.GetChild(1), false);
camera.transform.localPosition = new Vector3 (0, 0, 0);
// Enable the mouselookscript of the camera and make this object the characterBody
NewMouseLook mouselookscript = camera.GetComponent<NewMouseLook>();
mouselookscript.enabled = true;
mouselookscript.characterBody = gameObject;
rb = GetComponent<Rigidbody>();
// Destroy health bar on local player
Destroy (gameObject.transform.GetChild(2).gameObject);
// Set Rect Transform of health to GUI
healthBar = GameObject.Find("ForegroundGUI").GetComponent<RectTransform>();
// Teleport player to the spawn location
transform.position = spawnLoc;
anim = GetComponent<Animator> ();
dead = false;
}
void FixedUpdate()
{
if (!isLocalPlayer || dead || currentHealth == 0)
{
return;
}
// Move the player
var z = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeedForwards;
rb.MovePosition(rb.position + transform.forward * z);
var x = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeedSideways;
rb.MovePosition (rb.position + transform.right * x);
anim.SetFloat ("Speed", Mathf.Abs(z) + Mathf.Abs(x));
}
void Update()
{
if (!isLocalPlayer)
{
return;
}
if (gameObject.GetComponent<PlayerController>().currentHealth == 0 && !dead) {
dead = true;
GetComponent<Animator> ().SetBool ("Dead", dead);
GetComponent<NetworkAnimator>().SetTrigger("Dead");
}
if (Input.GetKeyDown(KeyCode.Q) && !dead)
{
//dead = true;
//currentHealth = 0;
//currentHealth -= 100;
//GetComponent<Animator> ().SetBool ("Dead", dead);
//GetComponent<NetworkAnimator>().SetTrigger("Dead");
TakeDamage(100);
CmdFire ();
}
if (Input.GetKeyDown (KeyCode.Space) && isGrounded() == true && !dead)
{
rb.AddForce(new Vector3(0, 8, 0), ForceMode.Impulse);
}
// var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f; // Uses horizontal input for char rotation
//var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
//rb.MovePosition(new Vector3(0, 0, rb.position.z + z));
//rb.MovePosition(rb.position + transform.forward * z);
//rb.velocity = transform.forward * z;
//rb.AddTorque (new Vector3 (0, x, 0));
// transform.Rotate(0, x, 0); // Rotates player
//transform.Translate(0, 0, z);
}
[Command]
void CmdFire()
{
// Create the explosion from the explosion Prefab
var explosionObject = (GameObject)Instantiate (
explosion,
transform.position,
transform.rotation);
explosionObject.GetComponent<Explosion> ().spawner = gameObject;
NetworkServer.Spawn(explosionObject);
// Destroy the explosion after 15 seconds
// Destroy(explosionObject, 15.0f);
}
bool isGrounded()
{
RaycastHit hit;
if(Physics.Raycast(transform.position, new Vector3(0, -1), out hit, groundCheckDistance))
{
return true;
}
return false;
}
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
transform.position = spawnLoc;
anim.SetBool ("Dead", false);
}
}
public void TakeDamage(int amount)
{
if (!isServer)
{
return;
}
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
dead = true;
GetComponent<Animator> ().SetBool ("Dead", dead);
GetComponent<NetworkAnimator>().SetTrigger("Dead");
}
}
void OnChangeHealth (int health)
{
currentHealth = health;
healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
}
}
Edit: what I tried is to change the anim to GetComponent, I switched some things around and deleted some stuff. If you delete the check isServer then it kinda works but this creates more problems.
Answer by bramieboy100 · Jul 18, 2017 at 08:50 PM
I eventually solved this problem by rewriting the whole script. The final change that solved the problem was to put a hook on the dead variable and regulating the animation there.
Your answer
![](https://koobas.hobune.stream/wayback/20220612130510im_/https://answers.unity.com/themes/thub/images/avi.jpg)