Search Unity

Moving that "same" object with client

Discussion in 'Multiplayer' started by Di_o, May 13, 2019.

  1. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    62
    I know, this stuff is deprfecated and this quastion is out there in a billion ways. Still, I can't find anyting that helps me out. It really should not be that hard, but I'm struggeling.

    I'm spawning an object, that can be scaled and rotated by all players (UNET). Everything works fine on the server side. The host can rotate and scale it and it's perfectly transforming on the client side. It's just simply not working the other way around. Either my code complains about some missing authority or it's just not doing anything. The following code does not produce any errors, but onyl works Server -> Client.

    It's driving me mad...

    Code (CSharp):
    1. [NetworkSettings(sendInterval = 0.033f)]
    2.     public class CollabObject_RotScale : NetworkBehaviour
    3.     {
    4.  
    5.         private Transform uiRootPos, body;
    6.  
    7.         [SyncVar(hook = "OnRotUpdate")] Quaternion rot;
    8.         [SyncVar(hook = "OnScaleUpdate")] float scale;
    9.  
    10.         private void Awake()
    11.         {
    12.             uiRootPos = GameObject.Find("UIRootPos").transform;
    13.             body = transform.GetChild(0);
    14.             scale = body.transform.localScale.x;
    15.             transform.position = uiRootPos.position;
    16.         }
    17.  
    18.         void Update()
    19.         {
    20.             if(body.transform.localScale.x != scale)
    21.             {
    22.                 scale = body.transform.localScale.x;
    23.                 if(isLocalPlayer)
    24.                     CmdUpdateScale(body.transform.localScale.x);          
    25.             }
    26.  
    27.             if(body.transform.localRotation != rot)
    28.             {
    29.                 rot = body.transform.localRotation;
    30.                 if(isLocalPlayer)
    31.                     CmdUpdateRot(body.transform.rotation);
    32.             }        
    33.         }
    34.  
    35.         void OnRotUpdate(Quaternion newRot)
    36.         {
    37.             rot = newRot;
    38.             body.transform.rotation = newRot;
    39.         }
    40.  
    41.         void OnScaleUpdate(float newScale)
    42.         {
    43.             scale = newScale;
    44.             body.transform.localScale = Vector3.one * scale;
    45.         }
    46.  
    47.         [Command]
    48.         void CmdUpdateRot(Quaternion newRot)
    49.         {
    50.             rot = newRot;    
    51.         }
    52.  
    53.         [Command]
    54.         void CmdUpdateScale( float newScale)
    55.         {      
    56.             scale = newScale;
    57.         }
    58.     }

    Note that I'm not transforming the parent root but the 0th child of it.
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    You say you are spawning this object, which implies it is not the special Player object but just some other object you are spawning. But you are checking for isLocalPlayer, which is only for use on the special Player object. Is this the Player object the NetworkManager spawns, or just some other non-player object you are spawning yourself?
     
  3. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    62
    Yes it's not a player object. It's an object all players should be able scale and rotate. A logic that prevents people from manipulating it at the same time would be my next step.
    But yeah you're right isLocalPlayer might be the wrong thing here. It's just confusing to me that the whole thing works fine on the host side.

    Do you have any suggestions? Thank you for the reply!
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    It works on the host because when you change body.transform.localScale and body.transform.localRotation on the host, this gets picked up as a change from scale and rot int update, which causes them to be set, and then the syncvars update on the clients, which call the syncvar hooks.

    The same thing does not occur when making a change on the clients. Firstly you are making the mistake of setting the values of syncvars in Update on the clients. This breaks the whole point of syncvars, making them out of sync. You only update them on the server or inside a syncvar hook method on the client. Second, isLocalPlayer is always false on this object, so your Commands are never called. Third, a Command can only be called on a client when hasAuthority is true (except for the special Player GameObject for that client), and unless you have assigned authority of this object to this specific client then hasAuthority will be false and the Command will just produce a log message warning about lack of authority instead of actually being called on the server.

    The last part is why it is common to put all your Commands on a separate script on the Player GameObject. The script on this object needs to call a Command to update something on the server, you have that script call it on the Player object instead. This is also an example of why people say that the Unet HLAPI was never actually completed, because it is missing a lot of expected functionality. Alternatively you could send a Unet Message, which isn't tied to a specific GameObject and so doesn't involve the concept of object authority.
     
  5. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    62
    Allright, thank you for all this help, I'll rewire everything to the player then.

    I get why people really don't like this and why it's being replaced.

    KUDOS!