Search Unity

UNET Would be nice to be able to "switch" authority from one client to another

Discussion in 'UNet' started by Dreamaster, Sep 16, 2015.

  1. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    I'm using spawnwithAuthority to give players the ability to drive vehicles smoothly but I'd also like to switch them out... the only way I can see doing that now is to spawn a new vehicle when the player "gets in" (touches its trigger collider) and despawning it when he gets out, and replacing it with a server controlled one... then when the other player touches it, spawnwithAuthority replace it with that one.

    Am I making any sense?
     
  2. TehGM

    TehGM

    Joined:
    Nov 15, 2013
    Posts:
    89
    I was also wondering about it. I would prefer everything to be server controlled (multiple player objects), but as for now it's not possible - and so when my player's ships module gets destroyed, it gets deattached, and I want player to lose control over it then - so pass authority to server.
     
  3. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    NetworkIdentity.AssignClientAuthority()
     
    kinguhdahood5 and Dreamaster like this.
  4. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    OMG THAT WORKS PERFECTLY!!!! THANK YOU SO MUCH!!!!
    /developer hug
     
    Ethan722 likes this.
  5. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    SEAN!!! I think I found a bug with this. I just had 2 guys connect to my game and try it because I needed to make sure it is what I thought it is.

    Basically... when a client "takes authority" of the car, it ROCKS... the car moves and I see it go on the host. He presses "L" to get out, and that calls "RemoveClientAuthority" ... the OTHER client gets in... takes off and it ROCKS... everything is working perfect. He presses "L" and removes his authority. BUT... now "I" (the HOST) get in, and I AssignClientAuthority with my host connection and the car MOVES ON MY SCREEN but the NetworkTransform no longer updates the clients with the new position! OH NOES!!! I'm SO CLOSE MAN THIS IS KILLING ME. :D
     
  6. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Hm. setting authority to a local client connection is an interesting use case. I would not be surpised if that had not been tested.

    There is also NetworkIdentity.RemoveClientAuthority() which reverts control back to the server, but that is not quite the same as assigning authority to the local client on the host.
     
  7. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    The problem could possibly be then that I'm calling NetworkIdentity.AssignClientAuthority() with the HOST connection and that is what is making it "break"... I could try it without that call except I don't know an easy way to "know" if I'm a host and not a client when the player object hits the cars trigger collider. In my mind it should be "ok" to call that function with the host ID though, so I appreciate you looking into it. ;)
     
  8. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    I tried checking for "isClient" but that returns true even from the host player.
     
  9. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    Ahh... Host IDtoClientConnection is always "-1"?
     
  10. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Bug 728735 filed on this. Should be fixed in an upcoming patch release.
     
    asperatology and Dreamaster like this.
  11. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    SWEET! I was just going to tell you that without using the "AssignClientAuthority" from the host connection the host can't control it even though the client removed the authority.
     
  12. BmDeveloperz

    BmDeveloperz

    Joined:
    Jul 1, 2013
    Posts:
    62
    How did you manage to use "NetworkIdentity.AssignClientAuthority()" ? Can you give an example code please ?

    I read the doc but there arent any examples how to use this...

    thanks
     
  13. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    I don't have my notebook computer on me but as soon as I get home from work in 6 hours, I promise I'll show you how I did it.
     
  14. BmDeveloperz

    BmDeveloperz

    Joined:
    Jul 1, 2013
    Posts:
    62
    Thanks very much, i will be looking forward for your answer. Thats the only issue left that i should solve :)
     
  15. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Also interested in this. Going to test the new patch to see if I can change authority from host to client and keep it that way.
     
  16. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    So... on my "server spawned object" (in this case a car) I have a script that handles the trigger collision with the player... when the player collides the script calls a function on a script that is attached to the player object:

    void OnTriggerEnter(Collider other)
    {

    if (other.gameObject.tag == "Player")
    {
    other.gameObject.GetComponent<SwitchControllers>().DisablePlayerEnableCar();

    }
    }

    The script SwitchControllers attached to the players, DisablePlayerEnableCar does some activating/deactivating of components but the first thing we're interested in for this thread is here:

    public void DisablePlayerEnableCar()
    {
    if (!isLocalPlayer)
    return;
    Debug.Log("IDs: " + this.GetComponent<NetworkIdentity>().connectionToServer.connectionId.ToString());

    CmdServerAssignClient();
    this.GetComponent<PlayerCarController>().enabled = true;
    }

    The command to assign that connection looks like this:
    [Command]
    void CmdServerAssignClient()
    {
    GameObject CarServer = GameObject.Find("AssaultVehicle");
    CarServer.GetComponent<NetworkIdentity>().AssignClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

    }

    When the player presses "L" the swtichcontroller switch calls this command to remove his authority:

    [Command]
    void CmdServerRemoveClient()
    {
    GameObject CarServer = GameObject.Find("AssaultVehicle");

    CarServer.GetComponent<NetworkIdentity>().RemoveClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

    }
     
    Last edited: Sep 22, 2015
  17. Dreamaster

    Dreamaster

    Joined:
    Aug 4, 2014
    Posts:
    148
    So now... in order to "move the car" I have a PlayerCarController script on the player object, that applies the controls and sends those values to the Controller script attached to the vehicle. Without clientauthority this had to be a server command and that caused some "lag" from clients as well as a LOT of network traffic... instead now we're directly calling our version of the "local car" and it's sending it's networktransform data up the wire to the server as expected:
    void Start()
    {
    if (isLocalPlayer)
    {
    Car = GameObject.Find("AssaultVehicle");
    CarScript = Car.GetComponent<AssaultCarController>();
    }
    }
    void FixedUpdate()
    {
    if (!isLocalPlayer)
    return;

    float Steer = Input.GetAxis("Horizontal");
    float inputPower = Input.GetAxis("Vertical");

    if(PreviousPower != inputPower || PreviousSteer != Steer)
    {
    CarScript.CarControl(Steer, inputPower);
    // CmdCallCarScript(Steer, inputPower); // no longer needed with client authority
    PreviousSteer = Steer;
    PreviousPower = inputPower;
    }

    }
     
  18. BmDeveloperz

    BmDeveloperz

    Joined:
    Jul 1, 2013
    Posts:
    62
    Thanks, this is going to be really helpfull.
     
    Dreamaster likes this.
  19. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    Thanks for your valueable code, seems it is working but showing me this error:

    NullReferenceException: Object reference not set to an instance of an object
    UnityEngine.Networking.NetworkTransform.SendTransform () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkTransform.cs:1103)
    UnityEngine.Networking.NetworkTransform.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkTransform.cs:1031)

    I don't where is the problem as it showing in UNet HLAPI. Can you see this?
     
  20. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    Probably you have forget to check hasAuthority property before moving the player? Correct?
     
  21. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16
    Full script please.
     
  22. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
  23. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16
    Now my problem is "reference not set to an instance of an object".

    So far I have this script attached. attached to the object:

    using UnityEngine;
    using UnityEngine.Networking;
    using System.Collections;

    public class ObjectAuthority : NetworkBehaviour {

    private LocalAuthority LocAuthor;
    public NetworkIdentity ThisItem;
    public NetworkInstanceId ThisItem2;



    public void OnTriggerStay(Collider other)
    {
    if (other.gameObject.tag == "Player" && Input.GetKeyDown(KeyCode.F))
    {

    LocAuthor.assignAuth();
    }
    }
    }

    ////////////////////////////////
    and this script attached to the local player:


    using UnityEngine;
    using UnityEngine.Networking;
    using System.Collections;

    public class LocalAuthority : NetworkBehaviour {



    public void assignAuth()
    {
    if (!isLocalPlayer)
    return;

    Debug.Log("IDs: " + this.GetComponent<NetworkIdentity>().connectionToServer.connectionId.ToString());

    CmdAssignAuthority();
    }

    [Command]
    void CmdAssignAuthority()
    {
    GameObject assignAuthorityObj = GameObject.Find("Ball");
    // assignAuthorityObj.GetComponent<NetworkIdentity>().AssignClientAuthority(GetComponent<NetworkIdentity>().connectionToClient);
    assignAuthorityObj.GetComponent<NetworkIdentity>().AssignClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

    }
    }
     
  24. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    w
    ill you like to tell the line number
     
  25. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16
    It's line 28

    NullReferenceException: Object reference not set to an instance of an object
    ObjectAuthority.OnTriggerStay (UnityEngine.Collider other) (at Assets/Authority Test/ObjectAuthority.cs:28)

    the issue is in the ObjectAuthority script in the following part at line 28:

    LocAuthor.assignAuth();


    Note: I posted the link of the two scripts.
     

    Attached Files:

  26. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16
    Okay I solved that problem and a few other issues after that, so I get no errors concerning the script.. The only problem now is that it says I can't remove or assign authority to a actual player object. I'm using unity 5.42f

    Here are the scripts.
     

    Attached Files:

  27. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16
    Okay so far I can remove and assign client authority for the host spawned object that is spawned by G, by removing authority when player exits ball trigger, and assign authority when player enter ball trigger and presses F. However it doesn't work for on the client side. I get an error saying that the ball has a different owner even though the server says it's owned by the client. Here's the scripts at this point.
     

    Attached Files:

  28. MiddleEye

    MiddleEye

    Joined:
    Feb 9, 2017
    Posts:
    16