Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Syncvar Hook - How to update a new client?

Discussion in 'Multiplayer' started by bitbiome_llc, Nov 5, 2015.

  1. bitbiome_llc

    bitbiome_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    I'm still trying to understand server/client interaction. The documentation often leaves me with more questions than answers.

    This is a 2d top down game where the client players are just pannable cameras looking down on a board game.
    A Unit on the board is a gameobject with a child. The child also has a sprite renderer. NetworkTransform takes care of moving the object around, but the child sprite needs updating.

    Unit Script
    Code (CSharp):
    1. public class Unit : NetworkBehaviour {
    2.  
    3. [SyncVar(hook="UpdateSprite")]
    4.     public string spriteName;
    5.  
    6. void UpdateSprite (string newVal) {
    7.         spriteName = newVal;
    8. //This is a reference to the child sprite renderer
    9.         spriteRenderer.sprite = SpriteAssets.GetUnit(newVal);
    10.     }
    11.  
    12. }
    13.  
    Network Player Script (Only works on host)
    The following works once for the host. When spriteName is changed the syncvar hook is called and updates the sprites. However, when another player is added this does not work. I assume that setting the name to the same value does not trigger SetDirtyBit.

    Code (CSharp):
    1. public class NetworkPlayer : NetworkBehaviour {
    2.  
    3. public override void OnStartClient() {
    4.  
    5.         CmdBuildUnits();
    6.  
    7.     }
    8.  
    9. [Command]
    10.     public void CmdBuildUnits() {
    11.  
    12. //update character sprites
    13.         foreach(Unit unit in UnitManager.GetPlayerUnits().Values )
    14.         {
    15.             //send information to clients
    16.             unit.spriteName = unit.unitData.character.tokenName;
    17.         }
    18. }
    Network Player Script (Works for host and clients)
    The following works for new clients. Is this the best way to go about this? Can I set that syncvar as dirty to have it update without creating an RPC? I really wish the documentation had some better use examples. The example projects didn't help much.

    Code (CSharp):
    1. [Command]
    2.     public void CmdBuildUnits() {
    3.  
    4. //update character sprites
    5.         foreach(Unit unit in UnitManager.GetPlayerUnits().Values )
    6.         {
    7.             //send information to clients
    8.             RpcUpdateUnit(unit.gameObject,unit.unitData.character.tokenName);
    9.         }
    10.  
    11.   public void RpcUpdateUnit(GameObject unitGO, string spriteNameIn) {
    12.  
    13.         unitGO.GetComponent<Unit>().spriteRenderer.sprite = SpriteAssets.GetUnit(spriteNameIn);
    14. }
    Network Player Script (Works for host and clients) Most likely NOT the way to do this?
    The following does update the sprites on a new client. I'm pretty sure this is NOT the way to get the syncvar to update on clients. I've looked around for SetDirtyBit(), but I don't understand how to use it from the limited documentation about it. Can I force a syncvar to update? Or should I just use a RPC to update the client?

    Code (CSharp):
    1.  
    2.  
    3. [Command]
    4.     public void CmdBuildUnits() {
    5.  
    6. //update character sprites
    7.         foreach(Unit unit in UnitManager.GetPlayerUnits().Values )
    8.         {
    9.             //send information to clients
    10. unit.spriteName = "blah";
    11.             unit.spriteName = unit.unitData.character.tokenName;
    12.         }
    13. }
     
    Last edited: Nov 5, 2015
    christophermrau likes this.
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
  3. bitbiome_llc

    bitbiome_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    I am calling it from OnStartClient. The issue is the host does it first and sets the syncvar. When a client connects all the units have the default sprite of the prefab. Then I try to set the syncvar using OnStartClient to match the server syncvar value. But the value is the same so apparently it doesn't update the client. See my three different examples. My question is about how should one go about forcing the client to update. Should I just create a RPC for newly connecting clients? Can I set the syncvar as dirty?

    It appears that I am already doing what you suggested. See the examples.
     
    christophermrau likes this.
  4. OlliQueck

    OlliQueck

    Joined:
    Apr 11, 2013
    Posts:
    49
    any progress? Having the same problem. something like setdirty or syncnow for a syncvar would be nice.. my guess was to change the variable to 0 then back to its value whenever a new client connects to force the server to sync it
     
  5. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    SyncVars automatically update for new clients. There is something wrong with this setup. Can you post a repro case?
     
  6. hugebug

    hugebug

    Joined:
    Jun 10, 2015
    Posts:
    17