diff --git a/Assets/Mirror/Runtime/ClientScene.cs b/Assets/Mirror/Runtime/ClientScene.cs index bb1998127..f081417d4 100644 --- a/Assets/Mirror/Runtime/ClientScene.cs +++ b/Assets/Mirror/Runtime/ClientScene.cs @@ -479,6 +479,7 @@ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg) identity.transform.localPosition = msg.position; identity.transform.localRotation = msg.rotation; identity.transform.localScale = msg.scale; + identity.hasAuthority = msg.isOwner; // deserialize components if any payload // (Count is 0 if there were no components) @@ -490,14 +491,13 @@ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg) identity.netId = msg.netId; NetworkIdentity.spawned[msg.netId] = identity; - identity.pendingAuthority = msg.isOwner; // objects spawned as part of initial state are started on a second pass if (isSpawnFinished) { + identity.NotifyAuthority(); identity.OnStartClient(); CheckForLocalPlayer(identity); - identity.hasAuthority = identity.pendingAuthority; } } @@ -595,9 +595,9 @@ internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _) // use data from scene objects foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values.OrderBy(uv => uv.netId)) { - identity.hasAuthority = identity.pendingAuthority; if (!identity.isClient) { + identity.NotifyAuthority(); identity.OnStartClient(); CheckForLocalPlayer(identity); } @@ -669,6 +669,7 @@ internal static void OnHostClientSpawn(SpawnMessage msg) { localObject.hasAuthority = msg.isOwner; localObject.OnSetHostVisibility(true); + localObject.NotifyAuthority(); } } diff --git a/Assets/Mirror/Runtime/NetworkIdentity.cs b/Assets/Mirror/Runtime/NetworkIdentity.cs index d27c43912..b5924d687 100644 --- a/Assets/Mirror/Runtime/NetworkIdentity.cs +++ b/Assets/Mirror/Runtime/NetworkIdentity.cs @@ -84,29 +84,7 @@ public bool isServer /// bool isOwner; - public bool hasAuthority - { - get => isOwner; - set - { - bool previous = isOwner; - isOwner = value; - - if (previous && !isOwner) - { - OnStopAuthority(); - } - if (!previous && isOwner) - { - OnStartAuthority(); - } - } - } - - // whether this object has been spawned with authority - // we need hasAuthority and pendingOwner because - // we need to wait until all of them spawn before updating hasAuthority - internal bool pendingAuthority { get; set; } + public bool hasAuthority { get; internal set; } /// /// The set of network connections (players) that can see this object. @@ -237,6 +215,7 @@ internal void SetNotLocalPlayer() return; } hasAuthority = false; + NotifyAuthority(); } // this is used when a connection is destroyed, since the "observers" property is read-only @@ -572,6 +551,16 @@ internal void OnStartClient() } } + bool hadAuthority; + internal void NotifyAuthority() + { + if (!hadAuthority && hasAuthority) + OnStartAuthority(); + if (hadAuthority && !hasAuthority) + OnStopAuthority(); + hadAuthority = hasAuthority; + } + void OnStartAuthority() { if (networkBehavioursCache == null) @@ -886,6 +875,7 @@ internal void SetLocalPlayer() { isLocalPlayer = true; hasAuthority = true; + NotifyAuthority(); foreach (NetworkBehaviour comp in networkBehavioursCache) { diff --git a/Assets/Mirror/Runtime/NetworkServer.cs b/Assets/Mirror/Runtime/NetworkServer.cs index 68d8af1fb..17cdee8f9 100644 --- a/Assets/Mirror/Runtime/NetworkServer.cs +++ b/Assets/Mirror/Runtime/NetworkServer.cs @@ -817,6 +817,10 @@ public static bool AddPlayerForConnection(NetworkConnection conn, GameObject pla // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) identity.connectionToClient = (NetworkConnectionToClient)conn; + // special case, we are in host mode, set hasAuthority to true so that all overrides see it + if (conn is ULocalConnectionToClient) + identity.hasAuthority = true; + // set ready if not set yet SetClientReady(conn); @@ -1050,6 +1054,11 @@ internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnecti identity.Reset(); identity.connectionToClient = (NetworkConnectionToClient)ownerConnection; + // special case to make sure hasAuthority is set + // on start server in host mode + if (ownerConnection is ULocalConnectionToClient) + identity.hasAuthority = true; + identity.OnStartServer(false); if (LogFilter.Debug) Debug.Log("SpawnObject instance ID " + identity.netId + " asset ID " + identity.assetId);