I’ve encountered an issue where my syncvar works fine without a hook but as soon as i give it a hook it stops syncing on all the clients but it still works for the host. The hook is still called when i try to change the variable but the variable it self will not change at all. I can work around this issue by changing the variable again in the hook but this seems like a stupid solution. Any ideas why this problem occurs?
The Syncvar is changed from a IEnumerator which is called by a function that is called by a Command function
The way I understand it is that the hook function works as some kind of override. If you use a hook function, the variable won’t sync automatically anymore. So you have to do it manually by putting the change in the hook function. So actually changing the variable again in the hook is the way you’re supposed to do it 
Kind of like this:
[SyncVar(hook = "OnSomeValueChange")]
public int someValue;
public void OnSomeValueChange(int valueToChangeTo)
{
someValue = valueToChangeTo;
//Do the things you want to do in the Hook, like call another function or something
}
I suppose this is in there so you can execute code BEFORE actually changing the value.
Be careful with this; if you are a Host (i.e. Server + Local Client) the SyncVar will be set on the Server immediately, and as there is only one script, when you enter the Hook function the SyncVar will already be set.
This really tripped me up for about half a day…
My recommendation (based on my own experience trying to solve this problem) is to avoid using SyncVar Hooks and use [ClientRpc] functions instead, when you want to do Client-side things with SyncVar values. The most reliable workflow I’ve found for using SyncVars is:
STEP 1:
Use a [Command] function to tell the Server to update a SyncVar value across all networked instances.
STEP 2:
Within the [Command] function, call a [ClientRpc] function that tells all clients what you want them to do with the updated SyncVar value, and (important!) pass the updated value to clients as a parameter/argument in your ClientRpc function call.
(Don’t assume that a SyncVar value updated on the server will immediately update on the clients, too… there seems to be some latency issues here.)
==========
EXAMPLE:
(This approach seems to sync and execute on server/host + all clients reliably)
==========
[SyncVar]
public var serverSyncedVariable;
var clientHudDisplay;
void Start(){
CmdUpdateServerSyncedVariable("someNewValue");
}
[Command] //fn executed only on server
void CmdUpdateServerSyncedVariable(var newValue){
serverSyncedVariable = newValue;
//It's important to pass the correct updated value as a parameter in your Rpc function!
RpcTellAllClientsToUpdateHuds(newValue); //or ...(serverSyncedVariable);
}
[ClientRpc] //fn executed on all clients
void RpcTellAllClientsToUpdateHuds(var newValue){
//this syncs accurately
clientHudDisplay.text = newValue;
}
It is always good to test, but in my experience the intended way of working works perfectly in Unity 2017.1:
- Syncvars are correctly synchronised by the time OnStartClient() is called. This is true whether or not there is a hook.
- Hooks are not called on init, only on change. This is by design, so we have to live with it. When you do want it to be called the first time, call it in OnStartClient().
- When Syncvars with hooks are later changed on the server (via Cmd call from the client) the Syncvars on the clients and server are not changed. So this means that you have to do this in the hook method.
So if I am correct, the above second post of @monotoan where an Rpc call is used to indicate change is not needed and even not wanted because it is basically trying to reimplement the hook functionality, is complex and causes additional network traffic.