Reputation: 107
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;
}
}
}
Upvotes: 2
Views: 9719
Reputation: 370
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:
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.
Upvotes: 2