Skip to content

Commit 8a3ff45

Browse files
fix
Fixed issue with server only NetworkManager instance spawning the network prefab itself as opposed to creating an instance. Extracted the instantiation portion of a network prefab into an internal method that can be used for integration testing prefab instantiation and potentially other edge case scenarios.
1 parent 3577be7 commit 8a3ff45

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

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

1616
### Fixed
1717

18+
- Fixed issue where a sever only `NetworkManager` instance would spawn the actual `NetworkPrefab`'s `GameObject` as opposed to creating an instance of it. (#3160)
1819
- Fixed issue where only the session owner (as opposed to all clients) would handle spawning prefab overrides properly when using a distributed authority network topology. (#3160)
1920
- Fixed issue where an exception was thrown when calling `NetworkManager.Shutdown` after calling `UnityTransport.Shutdown`. (#3118)
2021
- Fixed issue where `NetworkList` properties on in-scene placed `NetworkObject`s could cause small memory leaks when entering playmode. (#3147)

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

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -736,12 +736,20 @@ public NetworkObject InstantiateAndSpawn(NetworkObject networkPrefab, ulong owne
736736
internal NetworkObject InstantiateAndSpawnNoParameterChecks(NetworkObject networkPrefab, ulong ownerClientId = NetworkManager.ServerClientId, bool destroyWithScene = false, bool isPlayerObject = false, bool forceOverride = false, Vector3 position = default, Quaternion rotation = default)
737737
{
738738
var networkObject = networkPrefab;
739-
// Host spawns the ovveride and server spawns the original prefab unless forceOverride is set to true where both server or host will spawn the override.
740-
// In distributed authority mode, we alaways get the override
741-
if (forceOverride || NetworkManager.IsHost || NetworkManager.DistributedAuthorityMode)
739+
// - Host and clients always instantiate the ovveride if one exists.
740+
// - Server instantiates the original prefab unless:
741+
// -- forceOverride is set to true =or=
742+
// -- The prefab has a registered prefab handler, then we let user code determine what to spawn.
743+
// - Distributed authority mode always spawns the ovveride if one exists.
744+
if (forceOverride || NetworkManager.IsClient || NetworkManager.DistributedAuthorityMode || NetworkManager.PrefabHandler.ContainsHandler(networkPrefab.GlobalObjectIdHash))
742745
{
743746
networkObject = GetNetworkObjectToSpawn(networkPrefab.GlobalObjectIdHash, ownerClientId, position, rotation);
744747
}
748+
else // Under this case, server instantiate the prefab passed in.
749+
{
750+
networkObject = InstantiateNetworkPrefab(networkPrefab.gameObject, networkPrefab.GlobalObjectIdHash, position, rotation);
751+
}
752+
745753
if (networkObject == null)
746754
{
747755
Debug.LogError($"Failed to instantiate and spawn {networkPrefab.name}!");
@@ -824,16 +832,37 @@ internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ow
824832
else
825833
{
826834
// Create prefab instance while applying any pre-assigned position and rotation values
827-
networkObject = UnityEngine.Object.Instantiate(networkPrefabReference).GetComponent<NetworkObject>();
828-
networkObject.transform.position = position ?? networkObject.transform.position;
829-
networkObject.transform.rotation = rotation ?? networkObject.transform.rotation;
830-
networkObject.NetworkManagerOwner = NetworkManager;
831-
networkObject.PrefabGlobalObjectIdHash = globalObjectIdHash;
835+
networkObject = InstantiateNetworkPrefab(networkPrefabReference, globalObjectIdHash, position, rotation);
832836
}
833837
}
834838
return networkObject;
835839
}
836840

841+
/// <summary>
842+
/// Instantiates a network prefab instance, assigns the base prefab <see cref="NetworkObject.GlobalObjectIdHash"/>, positions, and orients
843+
/// the instance.
844+
/// !!! Should only be invoked by <see cref="GetNetworkObjectToSpawn"/> unless used by an integration test !!!
845+
/// </summary>
846+
/// <remarks>
847+
/// <param name="prefabGlobalObjectIdHash"> should be the base prefab <see cref="NetworkObject.GlobalObjectIdHash"/> value and not the
848+
/// overrided value.
849+
/// (Can be used for integration testing)
850+
/// </remarks>
851+
/// <param name="networkPrefab">prefab to instantiate</param>
852+
/// <param name="prefabGlobalObjectIdHash"><see cref="NetworkObject.GlobalObjectIdHash"/> of the base prefab instance</param>
853+
/// <param name="position">conditional position in place of the network prefab's default position</param>
854+
/// <param name="rotation">conditional rotation in place of the network prefab's default rotation</param>
855+
/// <returns>the instance of the <see cref="NetworkObject"/></returns>
856+
internal NetworkObject InstantiateNetworkPrefab(GameObject networkPrefab, uint prefabGlobalObjectIdHash, Vector3? position, Quaternion? rotation)
857+
{
858+
var networkObject = UnityEngine.Object.Instantiate(networkPrefab).GetComponent<NetworkObject>();
859+
networkObject.transform.position = position ?? networkObject.transform.position;
860+
networkObject.transform.rotation = rotation ?? networkObject.transform.rotation;
861+
networkObject.NetworkManagerOwner = NetworkManager;
862+
networkObject.PrefabGlobalObjectIdHash = prefabGlobalObjectIdHash;
863+
return networkObject;
864+
}
865+
837866
/// <summary>
838867
/// Creates a local NetowrkObject to be spawned.
839868
/// </summary>

0 commit comments

Comments
 (0)