How do I properly manage Client Authority on Objects? (Code inside)

Hello everyone. So I’m working on a little VR game right now and to no surprise it involve a lot of interaction with objects. Basically a player can pick something up and throw it etc.

In order to make the interaction itself as smooth as possible for the player I assign the authority over the objects he wants to pick up to said player (right when a player tries to pick something up). That means when he picks something up he gets the authority and when he puts it back down he loses authority. This way another player can pick the object up and so on.

All of this works very well but this system has one big flaw and that is throwing an object. The player loses authority the instance he lets go of it and the server gets the authority but all of this happens mid throw, which doesn’t work very well.

In order to fix the problem I just wanna check the authority whenever the player picks an object up. So lets say Player 1 picks an object up and gets authority, he then throws it towards player 2. When player 2 tries to catch it the server checks if player 2 has authority and if he doesn’t the server removes authority from player 1 and gives it to player 2. This should make throwing much smoother, since it will happen on the client that throws the object.

This is the current (not working) implementation of this system:

public void SetAuth (NetworkInstanceId objID, NetworkIdentity playerID)
  {
  if (!isLocalPlayer) return;
  CmdSetAuth(objID, playerID);
  }

[Command]
    public void CmdSetAuth(NetworkInstanceId objectId, NetworkIdentity player)
    {
        var iObject = NetworkServer.FindLocalObject(objectId);
        var networkIdentity = iObject.GetComponent<NetworkIdentity>();
        var otherOwner = networkIdentity.clientAuthorityOwner;

        if (networkIdentity.connectionToClient == base.connectionToClient)
        {
            return;
        }else
        {
            networkIdentity.RemoveClientAuthority(otherOwner);
            networkIdentity.AssignClientAuthority(player.connectionToClient);
        }      
    }

So this command is part of the player object and the function SetAuth(), too. The object the gets picked up calls the function SetAuth() and the function calls the command.

So what could possibly go wrong here?

Okay I found my misstake. The initial if was wrong and was comparing the wrong connection IDs. This works flawlessly now:

[Command]
    public void CmdSetAuth(NetworkInstanceId objectId, NetworkIdentity player)
    {
        var iObject = NetworkServer.FindLocalObject(objectId);
        var networkIdentity = iObject.GetComponent<NetworkIdentity>();
        var otherOwner = networkIdentity.clientAuthorityOwner;      

        if (otherOwner == player.connectionToClient)
        {
            return;
        }else
        {
            if (otherOwner != null)
            {
                networkIdentity.RemoveClientAuthority(otherOwner);
            }
            networkIdentity.AssignClientAuthority(player.connectionToClient);
        }      
    }
3 Likes