Search Unity

Help with sync vars when a new player joins?

Discussion in 'Multiplayer' started by sourlime99, Oct 12, 2017.

  1. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    I have a sync var health. if one player is in the server and he takes damage and then some one joines it still shows the other person to have full health how do i do this? Confused tbh
     
  2. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    The connecting Player should be getting the latest state of the SyncVar on connect. Can you post your code?
     
  3. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    yes sure
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using UnityEngine.Networking;
    5. using System.Collections;
    6.  
    7. public class Health : NetworkBehaviour
    8. {
    9.    
    10.     public const int maxHealth = 100;
    11.     public bool destroyOnDeath;
    12.  
    13.     //UI
    14.     public GameObject HealthText;
    15.     public GameObject DamgeImage;
    16.  
    17.     private Shooting ShootingScript;
    18.  
    19.     [SyncVar(hook = "OnChangeHealth")] <------------------- the sync var i use fpr health
    20.     public int currentHealth = maxHealth;
    21.  
    22.     public RectTransform healthBar;
    23.     //creates an array of all the spawn points
    24.     private NetworkStartPosition[] spawnPoints;
    25.  
    26.     private Camera_Script cameraScript;
    27.     private Vector3 DeathPoint;
    28.     void Start()
    29.     {
    30.         DeathPoint = new Vector3(0f, -150f, 0f);
    31.         if (isLocalPlayer)
    32.         {
    33.             cameraScript = gameObject.GetComponent<Camera_Script>();
    34.          
    35.             spawnPoints = FindObjectsOfType<NetworkStartPosition>();
    36.             ShootingScript = GetComponent<Shooting>();
    37.         }
    38.     }
    39.     void Update()
    40.     {
    41.         if (!isLocalPlayer)
    42.         {
    43.             return;
    44.         }
    45.         if (isLocalPlayer)
    46.         {              
    47.             //calls a respawn buy setting there health to zero by calling it to the server;    
    48.             if (Input.GetKeyDown(KeyCode.Y))
    49.             {
    50.                 CmdRespawn();
    51.             }
    52.            
    53.         }
    54.     }
    55.     //Shoud ONLY be called by server!
    56.     public bool TakeDamage(int amount)
    57.     {
    58.        
    59.         if (!isServer)
    60.             return false;
    61.         //takes the input amount from the shooting script and deducts the damage
    62.         currentHealth -= amount;
    63.    
    64.  
    65.  
    66.         //Handels Death
    67.         if (currentHealth <= 0)
    68.         {
    69.             Death();
    70.             if (destroyOnDeath)
    71.             {
    72.                 return false;
    73.             }
    74.             return true;
    75.         }
    76.         return false;
    77.     }
    78.     public void Death()
    79.     {
    80.         if (!isServer)
    81.             return;
    82.         //If the gameobject has destroy on death checks then dont respawn it!
    83.         if (destroyOnDeath)
    84.         {
    85.             Destroy(gameObject);
    86.         }
    87.         else
    88.         {
    89.  
    90.  
    91.            
    92.             transform.position = DeathPoint;
    93.             StartCoroutine(WaitForRespawn());
    94.  
    95.            // CanvasScript.canvas.WriteGameStatusText("Resapawning");
    96.  
    97.  
    98.             //Sets the max health to 100 maybe need to change later on when comes to respawning for rounds
    99.            // currentHealth = maxHealth;
    100.             // called on the Server, invoked on the Clients
    101.          //   RpcRespawn();
    102.         }
    103.     }
    104.  
    105.     // called when the varable health is changed
    106.     void OnChangeHealth(int currentHealth)
    107.     {
    108.         if(isLocalPlayer)
    109.         {
    110.             CanvasScript.canvas.SetHealth(currentHealth);
    111.             if (currentHealth == 0)
    112.             {
    113.                 CanvasScript.canvas.WriteGameStatusText("You ARE DEAD!!!!!!!");
    114.                 cameraScript.UpdateCamerasTo(false);
    115.  
    116.                 gameObject.GetComponent<PlayerController>().enabled = false;
    117.                 gameObject.GetComponent<SwitchGuns>().enabled = false;
    118.             }
    119.             if (currentHealth == 100)
    120.             {
    121.                 CanvasScript.canvas.WriteGameStatusText("");
    122.                 cameraScript.UpdateCamerasTo(true);
    123.  
    124.                 gameObject.GetComponent<PlayerController>().enabled = true;
    125.                 gameObject.GetComponent<SwitchGuns>().enabled = true;
    126.             }
    127.         }
    128.         healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    129.         if (!isClient)
    130.         {
    131.             HealthText.GetComponent<Text>().text = currentHealth.ToString();
    132.         }
    133.        
    134.     }
    135.  
    136.  
    137.     [ClientRpc]
    138.     void RpcRespawn()
    139.     {
    140.         if (isLocalPlayer)
    141.         {
    142.             // Set the spawn point to origin as a default value
    143.             Vector3 spawnPoint = Vector3.zero;
    144.  
    145.             // If there is a spawn point array and the array is not empty, pick one at random
    146.             if (spawnPoints != null && spawnPoints.Length > 0)
    147.             {
    148.                 spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
    149.             }
    150.  
    151.             // Set the player’s position to the chosen spawn point
    152.             //!!!!! Change this later for when there dead display ui and make invisiable or add to spectators teamf or example
    153.             transform.position = spawnPoint;
    154.            
    155.         }
    156.     }
    157.     [Command]
    158.     public void CmdRespawn()
    159.     {
    160.  
    161.         TakeDamage(1000);
    162.     }
    163.  
    164.     IEnumerator WaitForRespawn()
    165.     {
    166.  
    167.         yield return new WaitForSeconds(3f);
    168.         //Sets the max health to 100 maybe need to change later on when comes to respawning for rounds
    169.         currentHealth = maxHealth;
    170.         if (isLocalPlayer)
    171.  
    172.             // called on the Server, invoked on the Clients
    173.             RpcRespawn();
    174.            
    175.      
    176.     }
    177.     //IEnumerator WaitForRespawnClient()
    178.     //{
    179.  
    180.     //    yield return new WaitForSeconds(3f);
    181.  
    182.    //     CanvasScript.canvas.WriteGameStatusText("");
    183.    //     cameraScript.UpdateCamerasTo(true);
    184.  
    185.     //    gameObject.GetComponent<PlayerController>().enabled = true;
    186.     //    gameObject.GetComponent<SwitchGuns>().enabled = true;
    187.        
    188.  
    189.   //  }
    190.  
    191.  
    192. }
     
  4. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    forgot to put in comments didnt know if you would get a notifation
     
    LaneFox likes this.
  5. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    Is the actual variable inaccurate or does your UI simply not update? Looks like you're only updating the UI when it uses the hook, and it wouldn't be used unless the health changed.
     
  6. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    How would u recommended i update the UI? I mad a gif of what happens not very clear but i think your get it
    https://gyazo.com/923a16e22809c2e906327fa98f9ed480
     
  7. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    Move your UI updates to a separate method, call it from the hook and also call it from OnStartClient().

    When OnStartClient() fires, it is guaranteed to have the SyncVars ready and correct, so just tell the UI to update and voila.
     
  8. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    so make a method like UpdateUI() and in that move the stuff that handels the ui think and then in the network manager add something to call updateui() when they connect?
     
  9. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    i moved the stuff out the rpc but now what do i put here
    public override void OnStartClient(NetworkClient client)
    {
    base.OnStartClient(client);
    something .getgameobject etc
    }
    shall i use a loop and get every gameobejct with tag or is there someway to use the client in the overirde method.
     
  10. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    Basically, something like this.

    Code (csharp):
    1.  
    2.         [SyncVar(hook = "OnHealthChange")]
    3.         public float Health;
    4.         public Text MyHealthUi;
    5.  
    6.         public void OnStartClient()
    7.         {
    8.             // syncvar is already updated and ready at this point.
    9.             UpdateUi();
    10.         }
    11.  
    12.         public void OnHealthChange()
    13.         {
    14.             if (Health <= 0) Debug.Log("Im dead.");
    15.             UpdateUi();
    16.         }
    17.  
    18.         public void UpdateUi()
    19.         {
    20.             // use the syncvar
    21.             MyHealthUi.text = Health.ToString();
    22.         }
    OnStartClient reference.
     
  11. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    Ahh so its in the same script not the network manager ok ill give
     
  12. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    I did this however it doesnt update at all
    }
    UpdateHealthBar();
    //healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    // if (!isClient)
    //{
    // HealthText.GetComponent<Text>().text = currentHealth.ToString();
    //}

    }
    void UpdateHealthBar()
    {
    healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    if (!isClient)
    {
    HealthText.GetComponent<Text>().text = currentHealth.ToString();
    }
    }
    public override void OnStartClient()
    {
    base.OnStartClient();
    UpdateHealthBar();
    }
     
  13. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Looks like you already understand, but for anyone else reading this thread that is not understanding the issue, syncvars themselves should have the correct value when the new player joins, but syncvar hooks are not called. They are only called when the value changes, but a new player joining and getting the latest value is not considered a syncvar value change. So you have to do whatever you need to ensure things that use the syncvar are setup correctly yourself.
     
  14. sourlime99

    sourlime99

    Joined:
    Apr 19, 2013
    Posts:
    16
    Yer i understand the logic now the sync var just stores the value but you need to disaply it, but its now only updating on the server and not on any clients do i need it in a clientRpc?
     
  15. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Haven't saw it in a spaghetti code, but make sure that you're actually applying value inside SyncVar hook method to the SyncVar itself. Otherwise it won't work.