Skip to content

Commit d218b29

Browse files
fix: alternate player spawning no players or networkclient player registration (#3122)
* fix This resolves the issue where the player object was not being set properly if using alternate instantiate and spawn methods. * test Adjusted the ValidatePlayerObjects test to spawn players the 3 different ways and to validate the NetworkSpawnManager.PlayerObjects contains the newly spawned player on all instances and NetworkClient.PlayerObject is properly set on the owning client's NetworkManager. * update adding changelog entry * update adding the PR number to the changelog entry.
1 parent edc8b78 commit d218b29

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1414

1515
### Fixed
1616

17+
- Fixed issue where spawning a player using `NetworkObject.InstantiateAndSpawn` or `NetworkSpawnManager.InstantiateAndSpawn` would not update the `NetworkSpawnManager.PlayerObjects` or assign the newly spawned player to the `NetworkClient.PlayerObject`. (#3122)
1718
- Fixed issue where queued UnitTransport (NetworkTransport) message batches were being sent on the next frame. They are now sent at the end of the frame during `PostLateUpdate`. (#3113)
1819
- Fixed issue where `NotOwnerRpcTarget` or `OwnerRpcTarget` were not using their replacements `NotAuthorityRpcTarget` and `AuthorityRpcTarget` which would invoke a warning. (#3111)
1920
- Fixed issue where client is removed as an observer from spawned objects when their player instance is despawned. (#3110)

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,15 @@ internal NetworkObject InstantiateAndSpawnNoParameterChecks(NetworkObject networ
751751
networkObject.IsPlayerObject = isPlayerObject;
752752
networkObject.transform.position = position;
753753
networkObject.transform.rotation = rotation;
754-
networkObject.SpawnWithOwnership(ownerClientId, destroyWithScene);
754+
// If spawning as a player, then invoke SpawnAsPlayerObject
755+
if (isPlayerObject)
756+
{
757+
networkObject.SpawnAsPlayerObject(ownerClientId, destroyWithScene);
758+
}
759+
else // Otherwise just spawn with ownership
760+
{
761+
networkObject.SpawnWithOwnership(ownerClientId, destroyWithScene);
762+
}
755763
return networkObject;
756764
}
757765

com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,21 @@ private bool ValidatePlayerObjectOnClients(NetworkManager clientToValidate)
216216
m_ErrorLogLevel2.Append($"[Client-{client.LocalClientId} Prefab Mismatch][Expected GlobalObjectIdHash: {expectedGlobalObjectIdHash} but was {remoteNetworkClient.PlayerObject.GlobalObjectIdHash}]");
217217
success = false;
218218
}
219+
220+
var foundPlayer = false;
221+
foreach (var playerObject in client.SpawnManager.PlayerObjects)
222+
{
223+
if (playerObject.NetworkObjectId == clientToValidate.LocalClient.PlayerObject.NetworkObjectId)
224+
{
225+
foundPlayer = true;
226+
break;
227+
}
228+
}
229+
if (!foundPlayer)
230+
{
231+
m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkSpawnManager.PlayerObjects)} does not contain {clientToValidate.LocalClient.PlayerObject.name}!");
232+
success = false;
233+
}
219234
}
220235
return success;
221236
}
@@ -231,6 +246,12 @@ private bool ValidateAllPlayerObjects()
231246
m_ErrorLogLevel1.AppendLine($"[Client-{m_ServerNetworkManager.LocalClientId}]{m_ErrorLogLevel2}");
232247
success = false;
233248
}
249+
250+
if (m_ServerNetworkManager.LocalClient.PlayerObject == null)
251+
{
252+
m_ErrorLogLevel1.AppendLine($"[Client-{m_ServerNetworkManager.LocalClientId}] Local {nameof(NetworkClient.PlayerObject)} is null!");
253+
success = false;
254+
}
234255
}
235256

236257
foreach (var client in m_ClientNetworkManagers)
@@ -240,6 +261,17 @@ private bool ValidateAllPlayerObjects()
240261
m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}]{m_ErrorLogLevel2}");
241262
success = false;
242263
}
264+
if (client.LocalClient.PlayerObject == null)
265+
{
266+
m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkClient.PlayerObject)} is null!");
267+
success = false;
268+
}
269+
else
270+
if (!client.SpawnManager.PlayerObjects.Contains(client.LocalClient.PlayerObject))
271+
{
272+
m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}] Local {nameof(NetworkSpawnManager.PlayerObjects)} does not contain {client.LocalClient.PlayerObject.name}!");
273+
success = false;
274+
}
243275
}
244276

245277
return success;
@@ -250,12 +282,19 @@ private NetworkObject GetRandomPlayerPrefab()
250282
return m_PlayerPrefabs[Random.Range(0, m_PlayerPrefabs.Count() - 1)].GetComponent<NetworkObject>();
251283
}
252284

285+
public enum PlayerSpawnTypes
286+
{
287+
Normal,
288+
NetworkObject,
289+
SpawnManager
290+
}
291+
253292
/// <summary>
254293
/// Validates that when a client changes their player object that all connected client instances mirror the
255294
/// client's new player object.
256295
/// </summary>
257296
[UnityTest]
258-
public IEnumerator ValidatePlayerObjects()
297+
public IEnumerator ValidatePlayerObjects([Values] PlayerSpawnTypes playerSpawnType)
259298
{
260299
// Just do a quick validation for all connected client's NetworkClients
261300
yield return WaitForConditionOrTimeOut(AllNetworkClientsValidated);
@@ -268,14 +307,51 @@ public IEnumerator ValidatePlayerObjects()
268307
if (m_UseHost)
269308
{
270309
playerPrefabToSpawn = GetRandomPlayerPrefab();
271-
playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, m_ServerNetworkManager);
310+
switch (playerSpawnType)
311+
{
312+
case PlayerSpawnTypes.Normal:
313+
{
314+
playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, m_ServerNetworkManager);
315+
break;
316+
}
317+
case PlayerSpawnTypes.NetworkObject:
318+
{
319+
playerInstance = NetworkObject.InstantiateAndSpawn(playerPrefabToSpawn.gameObject, m_ServerNetworkManager, isPlayerObject: true).gameObject;
320+
break;
321+
}
322+
case PlayerSpawnTypes.SpawnManager:
323+
{
324+
playerInstance = m_ServerNetworkManager.SpawnManager.InstantiateAndSpawn(playerPrefabToSpawn, isPlayerObject: true).gameObject;
325+
break;
326+
}
327+
}
328+
272329
m_ChangedPlayerPrefabs.Add(m_ServerNetworkManager.LocalClientId, playerPrefabToSpawn.GlobalObjectIdHash);
273330
}
274331

275332
foreach (var client in m_ClientNetworkManagers)
276333
{
277334
playerPrefabToSpawn = GetRandomPlayerPrefab();
278-
playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, client);
335+
var networkManager = m_DistributedAuthority ? client : m_ServerNetworkManager;
336+
337+
switch (playerSpawnType)
338+
{
339+
case PlayerSpawnTypes.Normal:
340+
{
341+
playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, client);
342+
break;
343+
}
344+
case PlayerSpawnTypes.NetworkObject:
345+
{
346+
playerInstance = NetworkObject.InstantiateAndSpawn(playerPrefabToSpawn.gameObject, networkManager, client.LocalClientId, isPlayerObject: true).gameObject;
347+
break;
348+
}
349+
case PlayerSpawnTypes.SpawnManager:
350+
{
351+
playerInstance = networkManager.SpawnManager.InstantiateAndSpawn(playerPrefabToSpawn, client.LocalClientId, isPlayerObject: true).gameObject;
352+
break;
353+
}
354+
}
279355
m_ChangedPlayerPrefabs.Add(client.LocalClientId, playerPrefabToSpawn.GlobalObjectIdHash);
280356
}
281357

0 commit comments

Comments
 (0)