Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

SyncVar not updating on clients when used with hook

Discussion in 'Multiplayer' started by Neran28, Jul 15, 2017.

  1. Neran28

    Neran28

    Joined:
    Mar 14, 2016
    Posts:
    15
    Im working through this tutorial https://unity3d.com/de/learn/tutorials/topics/multiplayer-networking
    SyncVar is used to synchronize the current health values applied on the server with the clients. Because the healthbars are not synchronized hook= is used to update them on the clients in chapter 14. As soon as hook= is used the currentHealth values are no longer updated in (the inspector of) the clients but only in the servers. The healthbars work correctly.

    This is the code so far:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.Networking;
    6.  
    7. public class Health : NetworkBehaviour {
    8.  
    9.     public const int maxHealth = 100;
    10.  
    11.     [SyncVar(hook = "OnChangeHealth")]
    12.     public int currentHealth = maxHealth;
    13.     public RectTransform healthBar;
    14.  
    15.     public void TakeDamage(int amount)
    16.     {
    17.         if (!isServer)
    18.         {
    19.             return;
    20.         }
    21.  
    22.         currentHealth -= amount;
    23.         if(currentHealth <= 0)
    24.         {
    25.             currentHealth = 0;
    26.             RpcRepawn();
    27.         }
    28.  
    29.     }
    30.  
    31.     [ClientRpc]
    32.     void RpcRepawn()
    33.     {
    34.         if(isLocalPlayer)
    35.         {
    36.             transform.position = Vector3.zero;
    37.         }
    38.     }
    39.  
    40.     void OnChangeHealth(int currentHealth)
    41.     {
    42.         healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    43.     }
    44. }
    45.  
    I dont understand why the values in the inspector wont update anymore. As far as I undestood this, SyncVars are synchronized with the clients and then when they change the function is called.
    If I include a print if the currentHealth is below a threshold in TakeDamage() it wont happen, which means that the value indeed does not update.
    If I reconnect the client the players health values are correct. If the health values change again they wont update until the client reconnects.
     
  2. Deleted User

    Deleted User

    Guest


    You should manually assign the new value of health.
    There is an error on official unity post.

    Code (CSharp):
    1. void OnChangeHealth(int newHealth)
    2.     {
    3.         currentHealth = newHealth; //fix
    4.         healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    5.     }
     
    Neran28 likes this.
  3. marcV2g

    marcV2g

    Joined:
    Jan 11, 2016
    Posts:
    115
    monotoan likes this.
  4. Neran28

    Neran28

    Joined:
    Mar 14, 2016
    Posts:
    15
    Thanks for the reply. What do you mean by "error"? Unity Engine bug or error in the tutorial? If this is intended then im confused why because its still a SyncVar isnt it?

    https://docs.unity3d.com/ScriptReference/Networking.SyncVarAttribute-hook.html

    It also seems that the docs and the tutorial are not consistent. In the docs there is written "... a function to be called when the sync var changes value on the client". So for me this means that the server recognizes a change and then synchronizes the new value with the clients. Then the assigned function is called only on the clients. While in the tutorial there is written " These functions are invoked on the Server and all Clients when the value of the SyncVar changes".

    Also if the doc is right, how comes that the function is called on the client even though the value did not change on the client?
     
  5. Deleted User

    Deleted User

    Guest

    The value doesn't assign when hook is called. I gave you a fix and an explanation already.
     
    Last edited by a moderator: Jul 15, 2017
  6. monotoan

    monotoan

    Joined:
    Feb 13, 2015
    Posts:
    11
    Yeah, it really seems like SyncVar hooks are broken. The ideal behavior -- and what the documentation implies -- is that a hook should act like what we'd call a "callback" or "delegate" in many other coding situations. That is, when the value of a SyncVar changes, the hook function fires to execute follow-up actions in response to that change.

    But if a SyncVar Hook blocks the updating of the value or fires before it's actually updated (which seems to be the case), then it defeats the whole purpose of the hook in my view. Manually updating the SyncVar value within the hook may work as a fix, but it's a hacky one and doesn't really support good Networking practice. If the whole purpose of SyncVars is that they're consistently and automatically synced across all clients, developers shouldn't be able to accidentally or intentionally block that syncing just by adding a hook.
     
  7. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    A SyncVar hook doesn't update the SyncVar itself to allow you the opportunity to still use the old value in your hook function. For example if a SyncVar represented a player's score, and the server increased the score by +2, the client would get the SyncVar hook function called and still has the old score in the SyncVar. So the client can then subtract the old score from the new one, and can throw some cool "+2 Points!" thing on the screen, then update the client version of the SyncVar with the new value.

    Otherwise either the client would need to store another copy of the SyncVar value, or the server would need to call a separate CllientRpc, to get something as simple as telling the client how much a SyncVar has changed instead of just its current value.

    I believe this is as designed behavior, but I don't believe it is in any of the documentation (UNET HLAPI docs are not very thorough).
     
    Last edited: Jan 29, 2018
  8. monotoan

    monotoan

    Joined:
    Feb 13, 2015
    Posts:
    11
    Thanks for the explanation -- I can see the value in that. Personally, I think it's less valuable than having variables with reliable consistent values across all network instances, especially when there are other ways to track variable changes. But the main problem remains that this behavior is not what Unity Documentation or Tutorials would lead anyone to expect. I've logged feedback on the SyncVar hook Script Reference documentation page to highlight this.

    Also, further complicating this is that if a game instance is acting as a Host (i.e. both Server and Client), I believe the SyncVar value for that instance will already be updated when the hook fires for that Client -- but not for any other Guests/Clients. This leads to even more divergent and confusing behavior across the Network. Running one instance as a Host is the most common setup for people who are just learning UNET, so this seems like a pretty big stumbling block.
     
    Last edited: Jan 29, 2018
  9. curiousbrandon

    curiousbrandon

    Joined:
    Sep 22, 2017
    Posts:
    6
    Thanks for the thread. I spent a few hours trying to figure out why SyncVar wasn't working until I found this thread. This really should be added to the documentation for SyncVar and SyncVarAttribute.hook, especially when the attribute changes the way SyncVar works and creates inconsistency.
     
    Joe-Censored likes this.
  10. Tiberius1701

    Tiberius1701

    Joined:
    Sep 16, 2014
    Posts:
    71
    Thank you soooo much for this explanation and fix - luckily I started looking online as soon as I started to get the weird behavior. Hopefully a Unity Mod sees this and updates the tutorial - it is a great tutorial until it gets to this point.
     
  11. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Unet has been deprecated, so don't expect any documentation or tutorial updates for it.
     
  12. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    This is absolutely backwards and unintuitive!

    It needs to be documented somewhere, for the love of everything holy.

    Thank you for this thread and the investigative work.
     
    Last edited: Sep 25, 2018