2

I am making a turn based multiplayer game with Unity 2019.3.2f1 and am using Mirror to connect the players. My goal is to add player objects to the GameMaster script (as you will see in my bottom-most script), so that I can keep track of them and update their progress in the Player script. I have followed DapperDino's youtube tutorial (https://www.youtube.com/watch?v=oBRt9OifJvE&list=PLS6sInD7ThM1aUDj8lZrF4b4lpvejB2uB&index=2) and made a lobby copying everything from the tutorial except the spawner system and I've made adjustments to the names of the scenes, removed the map handler and instead simply have 2 scenes. After 2 players enter lobby, click ready and the host clicks Start, the MainMenu scene changes to GameScene and the actual game starts, but before that the function NetworkServer.ReplacePlayerForConnection(conn, gameplayerInstance.gameObject) is called, before the change of the scene. And I get this error:

RemoveClientAuthority can only be called on the server for spawned objects. UnityEngine.Logger:Log(LogType, Object) Mirror.ILoggerExtensions:LogError(ILogger, Object) (at Assets/Mirror/Runtime/LogFactory.cs:58) Mirror.NetworkIdentity:RemoveClientAuthority() (at Assets/Mirror/Runtime/NetworkIdentity.cs:1230) Mirror.NetworkServer:InternalReplacePlayerForConnection(NetworkConnection, GameObject, Boolean) (at Assets/Mirror/Runtime/NetworkServer.cs:843) Mirror.NetworkServer:ReplacePlayerForConnection(NetworkConnection, GameObject, Boolean) (at Assets/Mirror/Runtime/NetworkServer.cs:680) DapperDino.Mirror.Tutorials.Lobby.NetworkManagerLobby:ServerChangeScene(String) (at Assets/Lobby/Scripts/NetworkManagerLobby.cs:181) DapperDino.Mirror.Tutorials.Lobby.NetworkManagerLobby:StartGame() (at Assets/Lobby/Scripts/NetworkManagerLobby.cs:163)

Why should RemoveClientAuthority() be called?

Then I get this warning: Trying to send command for object without authority. Player.CmdAddPlayer

Here is my code. As you see, on update I check if(!hasAuthority) and if the client doesn't, I would return the Update function but it was never so I commented it to debug. The warning I get is on the host process, which baffles me. Shouldn't the host have authority as it is also the server?

using System.Collections.Generic;
using UnityEngine;
using Mirror;


public class Player : NetworkBehaviour
{
    GameMaster gameMaster=null;
    //public NetworkManager networkManager;

    public Country country;
    public List<Territory> controlledTerritories;
    public List<Army> armies = new List<Army>();
    public int gold;
    bool set = false;
    void Start()
    {
        //networkManager = GameObject.FindWithTag("NetworkManager").GetComponent<NetworkManager>();
    }
    [Client]
    void Update()
    {
        //Debug.Log(networkManager);
        if (!set)
        {
            if (!hasAuthority)
            {
                //return;
            }
            Debug.Log("About to call CmdAddPlayer()");
            //This is the furthest I get. I get the warning after trying to call CmdAddPlayer() and it isn't called
            CmdAddPlayer();
        }
    }
    [Command]
    void CmdAddPlayer()
    {
        //Validate logic here
        Debug.Log("Called CmdAddPlayer()");
        RpcAddPlayer();
    }

    [ClientRpc]
    void RpcAddPlayer()
    {
        Debug.Log("Called RpcPlayer()");
        GameObject _mapTmp = GameObject.FindWithTag("GameController");
        GameMaster _gameMasterTmp = null;
        if (_mapTmp != null)
        {
            _gameMasterTmp = _mapTmp.GetComponent<GameMaster>();
        }
        if (gameMaster == null && _gameMasterTmp != null)
        {
            gameMaster = _gameMasterTmp;
            gameMaster.players.Add(this);
            set = true;
        }
    }
}
4
  • Your Update is tagged Client, why? You removed the return for if(!hasAuthority) ... and you definitely do not want to call an RPC command every frame ...
    – derHugo
    Commented Jun 19, 2020 at 5:47
  • RemoveClientAuthority can only be called on the server for spawned objects. this means that you can not use it on the player objects but only on objects that where spawned by the host using Network.Spawn .. it would help to see the code where these errors are actually thrown e.g. your NetworkServer and NetworkIdendity .. otherwise it is hard to tell what is happening there if even you don't ^^
    – derHugo
    Commented Jun 19, 2020 at 5:56
  • I would like to share them with you here, but " Body is limited to 30000 characters; you entered 66975." You can see them once you Import Mirror. And you can also see the other scripts that are used in the tutorial here: github.com/DapperDino/Mirror-Multiplayer-Tutorials/tree/master/… Commented Jun 19, 2020 at 6:10
  • What baffles me is that my Player script structure and his Player script structure in Ownership are almost identical: github.com/DapperDino/Mirror-Multiplayer-Tutorials/blob/master/… and mine doesn't work. Commented Jun 19, 2020 at 6:13

1 Answer 1

2

I'm following the same tutorial and came across the same error.

Basically apparently its something to do with Mirror's ServerChangeScene.

You can solve this pretty easily. In DapperDino NetworkManagerLobby script, go to ServerChangeScene override, and get reid of the destroy so that it goes from this:

NetworkServer.Destroy(conn.identity.gameObject);     
NetworkServer.ReplacePlayerForConnection(conn, gameplayerInstance.gameObject); 
 

So that it is changed to:

 NetworkServer.ReplacePlayerForConnection(conn, gameplayerInstance.gameObject); 
 

This should fix it. The room player object seems to be destroyed automatically.

You can find out more about the error here if that doesn't work: https://github.com/vis2k/Mirror/issues/1593

To answer the second half of the problem, there's a good explanation here:

Unity3D. Trying to send command for object without authority

Basically, you may be trying to send a command from an object that doesn't have authority. So what does that mean?

You can only send a Command from YOUR player object, TO the player object which represents YOU on the other computer.

It's not clear from your code, but you could be:

  1. EITHER trying to send a command from the 'player' object that belongs to the other player (for example, if you're looping through all the players in the game).
  2. OR you've written a script called 'player' which hasn't been given authority (i suspect it is this one given you've called your object 'player' and not 'NetworkGamePlayer' as in the tutorial.

If you're trying to do the first, make sure you check if the player is the local player:

    void CallCommandMove(){
       if(!isLocalPlayer){
        return;
         }
       CmdMove();
    }

Alternatively, if you're trying to do the second, you need to give your own player object authority (as in the accepted answer in this thread: Unity3D. Trying to send command for object without authority

Finally, the easiest approach whilst learning is to simply put your code on the NetworkGamePlayer script.

6
  • 1
    N.B. this has been changed as i originally left in the destroy, but that kills your NetworkGamePlayer object. I'm also doing a turn based game so interested to hear how yours goes!
    – Truvia
    Commented Jun 20, 2020 at 11:14
  • Thank you very much. That's great, but answers half of my question. The other half remains: Why doesn't the host have authority? Commented Jun 23, 2020 at 9:32
  • 1
    Sorry for the delay in responding and for missing part of the issue: when i came across the error it was throwing an authority error because the NetworkGamePlayer wasn't replacing the NetworkRoomPlayer properly so it didn't have authority. However, it looks like you're trying to call a command from a different "Player" object here. I'm certainly no expert, but I think if you're going to call a command you have to put it in the NetworkGamePlayer script/object, as that is the actual player object with authority. I'll see if i can update the answer with a better explanation.
    – Truvia
    Commented Jun 26, 2020 at 14:19
  • I've updated my answer to address the second part, let me know if that answers. Happy to explain further
    – Truvia
    Commented Jun 26, 2020 at 14:39
  • Thank you for updating your answer and sorry for the big delay on my part. I have read your edit and to update you I have posted a link to an image representing the 2 types of player objects I have in the GameScene. Both have Network Identity. I call the Player script on the Player object and the NetworkGamePlayer object has only the NetworkGamePlayerLobby script. In the Ownership tutorial everything ran smoothly with the Player object being separate from the NetworkGamePlayer, but in my case the flags isLocalPlayer and hasAuthority are both false. Commented Jul 30, 2020 at 13:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.