Search Unity

[SOLVED]Need help understanding the way authority works in unity.

Discussion in 'Multiplayer' started by Infinity_way, Aug 2, 2017.

  1. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17
    I'm having a problem with my client players, if i start the script in a [Command] method, it does change my SyncVars on the server, but it DOESN'T change the unsync private ones inside it ... and if i start the script with a non-command method, it changes the private/public vars normally but when i make it call a [Command] after some those changes, it says i don't have authority to do so [on the console], although i am the local player(in this case, the client.) and the script is indeed attached to the player with a local player network identity...

    Also, if i make the first method non-command, i can't change a SyncVar to start the hook ...
    just calling a non-command method from a [Command] method seems to carry the "authority" of a command so it won't change normal Vars either.

    I've been making my way around it by settling things with a command FIRST and then changing a SynVar with a hook and THAT HOOK starts a non-command method which changes the other variables i want to change... My guess is that the hook calling the non-command method emerge from the script it self, so i has no longe the [Command] factor to it, therefore, it changes my normal vars...

    Is this the only way to that? or am i doing something wrong?
     
  2. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17
    nothing? anyone?
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Your post doesn't make sense. Start the script? Are you activating the script component right before you call a method within it?

    Some things that might help. Commands are run on the server only, so you need to be careful on what machine you are checking properties that are changed within a Command. So you're on a client and call a Command, the command changes a syncvar and another variable that is not a syncvar. You should not be checking on the client for that non-syncvar to change, as it is changed ONLY on the server. The syncvar changed by the command will propagate back to all clients. You're apparently not understanding that individual machines have their own versions of variables, and they will end up with different values when you change them on only one machine if they are not syncvars.

    Commands don't carry any "authority" to any non-command methods called within the command. Again, Commands are literally run on the server, so any method you call within that command is again only run on the server. Assuming the server has authority, that authority isn't just for individual methods, but for any method run on the server. So obviously when you run a command which only runs on the server, then any other methods called within that command are again ONLY run on the server, and will also have authority, and again any variables that are not syncvars changed on the server will not update on the clients, so stop checking on the clients for variables changed only on the server.

    Lastly, syncvars only propagate from the server to the clients. Changes to syncvars on clients will not push back to the server or any other clients. Use Commands to update syncvars.
     
    Infinity_way likes this.
  4. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17
    What i'm trying to do is a 4 slot inventory, i decided to not sync the whole array of information, only send the data that i actually interacted to the server.

    i'd gather the amount of times i can still interact with that object by:

    Code (CSharp):
    1.     [Command]
    2.     private void UpInteractionCount ()
    3.     {
    4.         TimesItWillInteract = OtherObject.GetComponent<UniversalPuzzle> ().TimesThisWillProvideOrRemove;
    5.         Debug.Log (TimesItWillInteract);
    6.     }
    than use this information to see if the player can actually continue with this action. if it returns positive, then the item will be added/removed from the inventory (which works fine), after that, a feed back is sent back to the server telling it that i made one interaction with it:

    Code (CSharp):
    1. [Command]
    2.     private void CmdUpdateUP ()
    3.     {
    4.        OtherObject.GetComponent<UniversalPuzzle> ().TimesThisWillProvideOrRemove--;
    5. }
    The "TimesThisWillProvideOrRemove" is a SyncVar inside UniversalPuzzle which has a hook with an "if" to make an action once it reaches Zero:

    Code (CSharp):
    1. [SyncVar(hook="Type10Activate")] public int TimesThisWillProvideOrRemove;
    Code (CSharp):
    1. public void Type10Activate (int Value)
    2.     {
    3.         if (Value == 0)
    4.         {
    5.             Debug.Log ("Hook Worked Password");
    6.             RandomObjectT10.SetActive (StateToChangeT10);        }
    7.     }
    but this only works (perfectly) on the host-client. The other client-clients won't gather the right value of "TimesThisWillProvideOrRemove" nor modify it.

    If i gather the information WITHOUT calling the [Command], it will not call an updated version of it.
    Exemple: even if the host interacts with it, it will always return "original"(stated on the inspector) value, therefore, the client can grab infinite amount of item from the Object lol.

    If i try to gather the value with a [Command], it just won't run the command (it displays no Debug.log) and doesn't gather anything at all. The Client will always see the "TimesThisWillProvideOrRemove" as "0", therefore, not getting anything...

    I successfully made other simpler scripts work, but this won't work...

    The "inventory" script is attached to the player and has Local Player Authority.
    The actual configuration is: Raycast.cs to get object -> send Obj info to -> Mediator.cs where it filter the type of UniversalPuzzle, if it's "Type10", it will send the info to -> Inventory.cs to process.
    UniversalPuzzle is just bunch of SyncVar stuffed in an Objects. The mediator and inventory pull the information from the UniversalPuzzle, process it and split results back to the object with the new values(all of them synced).
     
  5. Deleted User

    Deleted User

    Guest


    Code (CSharp):
    1. public void Type10Activate (int Value)
    2.     {
    3.         TimesThisWillProvideOrRemove = Value; // fix
    4.  
    5.         if (Value == 0)
    6.         {
    7.             Debug.Log ("Hook Worked Password");
    8.             RandomObjectT10.SetActive (StateToChangeT10);        }
    9.     }
     
    Infinity_way likes this.
  6. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17

    It solved my half of my problem XD thanks, if the host interact with it, the client see the changes but the client itself still won't send a command to change it. Only host-client can alter that value.

    this still won't work on clients:
    Code (CSharp):
    1. [Command]
    2.     private void CmdUpdateUP ()
    3.     {
    4.        OtherObject.GetComponent<UniversalPuzzle> ().TimesThisWillProvideOrRemove--;
    5. }
     
  7. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17
    It worked... unity is f***ing kidding with me...

    It wasn't sending the commands, so i decided to make a:
    Code (CSharp):
    1. Debug.log(LocalPlayerAuthority);
    to check the authority. it came back as "true" and started working :mad:

    ARRGHH.
    thanks for the assistance anyway ... i didn't thought CHECKING the authority in a DEBUG.LOG would make it "remember" it actually has god danm authority to change the danm thingh which i indeed named:
    Code (CSharp):
    1. [Command]
    2.     public void CmdAddTheDanmThing ()
    3.     {
    4.         TimesThisWillProvideOrRemove--;
    5.         Debug.Log ("added the Danm thingy.");
    6.     }
     
    xVergilx likes this.
  8. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I don't think it's because of it, but rather because of a change of code. It probably triggered UnetWeaver to rebuild generated code.
     
  9. Infinity_way

    Infinity_way

    Joined:
    Mar 21, 2017
    Posts:
    17
    So, i know i posted this a long time ago but now i got a little more used to it.

    A good way of making this work is to segment it within various kinds of different methods, if something run locally on the object, call a non-command and only call command when you need to change a syncvar or something like it. Kind of ... not be afraid of calling many and many methods just to filter the things you want to change.