Skip to content

refactor!: NetworkPrefabHandler and INetworkPrefabInstanceHandler API & XmlDoc changes #977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public class NetworkConfig
/// </summary>
internal Dictionary<uint, NetworkPrefab> NetworkPrefabOverrideLinks = new Dictionary<uint, NetworkPrefab>();

internal Dictionary<uint, uint> OverrideToNetworkPrefab = new Dictionary<uint, uint>();


/// <summary>
/// The tickrate of network ticks. This value controls how often MLAPI runs user code and sends out data.
/// </summary>
Expand Down
54 changes: 46 additions & 8 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr
internal static bool UseSnapshot = false;

private const double k_TimeSyncFrequency = 1.0d; // sync every second, TODO will be removed once timesync is done via snapshots

internal MessageQueueContainer MessageQueueContainer { get; private set; }


Expand All @@ -82,6 +82,37 @@ public NetworkPrefabHandler PrefabHandler
}
}

/// <summary>
/// Returns the <see cref="GameObject"/> to use as the override as could be defined within the NetworkPrefab list
/// Note: This should be used to create <see cref="GameObject"/> pools (with <see cref="NetworkObject"/> components)
/// under the scenario where you are using the Host model as it spawns everything locally. As such, the override
/// will not be applied when spawning locally on a Host.
/// Related Classes and Interfaces:
/// <see cref="NetworkPrefabHandler"/>
/// <see cref="INetworkPrefabInstanceHandler"/>
/// </summary>
/// <param name="gameObject">the <see cref="GameObject"/> to be checked for a <see cref="NetworkManager"/> defined NetworkPrefab override</param>
/// <returns>a <see cref="GameObject"/> that is either the override or if no overrides exist it returns the same as the one passed in as a parameter</returns>
public GameObject GetNetworkPrefabOverride(GameObject gameObject)
{
var networkObject = gameObject.GetComponent<NetworkObject>();
if (networkObject != null)
{
if (NetworkConfig.NetworkPrefabOverrideLinks.ContainsKey(networkObject.GlobalObjectIdHash))
{
switch (NetworkConfig.NetworkPrefabOverrideLinks[networkObject.GlobalObjectIdHash].Override)
{
case NetworkPrefabOverride.Hash:
case NetworkPrefabOverride.Prefab:
{
return NetworkConfig.NetworkPrefabOverrideLinks[networkObject.GlobalObjectIdHash].OverridingTargetPrefab;
}
}
}
}
return gameObject;
}

public NetworkTimeSystem NetworkTimeSystem { get; private set; }

public NetworkTickSystem NetworkTickSystem { get; private set; }
Expand Down Expand Up @@ -492,13 +523,22 @@ private void Initialize(bool server)
NetworkConfig.NetworkPrefabs[i]);
break;
case NetworkPrefabOverride.Prefab:
NetworkConfig.NetworkPrefabOverrideLinks.Add(
NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.GetComponent<NetworkObject>()
.GlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);
{
var sourcePrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.GetComponent<NetworkObject>().GlobalObjectIdHash;
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);

var targetPrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab.GetComponent<NetworkObject>().GlobalObjectIdHash;
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
}
break;
case NetworkPrefabOverride.Hash:
NetworkConfig.NetworkPrefabOverrideLinks.Add(
NetworkConfig.NetworkPrefabs[i].SourceHashToOverride, NetworkConfig.NetworkPrefabs[i]);
{
var sourcePrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].SourceHashToOverride;
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);

var targetPrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab.GetComponent<NetworkObject>().GlobalObjectIdHash;
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
}
break;
}
}
Expand Down Expand Up @@ -1276,7 +1316,6 @@ internal void OnClientDisconnectFromServer(ulong clientId)
if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].PlayerObject.GlobalObjectIdHash))
{
PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].PlayerObject);
SpawnManager.OnDespawnObject(ConnectedClients[clientId].PlayerObject, false);
}
else
{
Expand All @@ -1295,7 +1334,6 @@ internal void OnClientDisconnectFromServer(ulong clientId)
.GlobalObjectIdHash))
{
PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].OwnedObjects[i]);
SpawnManager.OnDespawnObject(ConnectedClients[clientId].OwnedObjects[i], false);
}
else
{
Expand Down
35 changes: 30 additions & 5 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public void NetworkShow(ulong clientId, Stream payload = null)

Observers.Add(clientId);

NetworkManager.SpawnManager.SendSpawnCallForObject(clientId, this, payload);
NetworkManager.SpawnManager.SendSpawnCallForObject(clientId, OwnerClientId, this, payload);
}

/// <summary>
Expand Down Expand Up @@ -442,12 +442,12 @@ private void SpawnInternal(Stream spawnPayload, bool destroyWithScene, ulong? ow
}

NetworkManager.SpawnManager.SpawnNetworkObjectLocally(this, NetworkManager.SpawnManager.GetNetworkObjectId(), false, playerObject, ownerClientId, spawnPayload, spawnPayload != null, spawnPayload == null ? 0 : (int)spawnPayload.Length, false, destroyWithScene);

ulong ownerId = ownerClientId != null ? ownerClientId.Value : NetworkManager.ServerClientId;
for (int i = 0; i < NetworkManager.ConnectedClientsList.Count; i++)
{
if (Observers.Contains(NetworkManager.ConnectedClientsList[i].ClientId))
{
NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ConnectedClientsList[i].ClientId, this, spawnPayload);
NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ConnectedClientsList[i].ClientId, ownerId, this, spawnPayload);
}
}
}
Expand All @@ -456,7 +456,7 @@ private void SpawnInternal(Stream spawnPayload, bool destroyWithScene, ulong? ow
/// Spawns this GameObject across the network. Can only be called from the Server
/// </summary>
/// <param name="spawnPayload">The writer containing the spawn payload</param>
/// <param name="destroyWithScene">Should the object be destroyd when the scene is changed</param>
/// <param name="destroyWithScene">Should the object be destroyed when the scene is changed</param>
public void Spawn(Stream spawnPayload = null, bool destroyWithScene = false)
{
SpawnInternal(spawnPayload, destroyWithScene, null, false);
Expand Down Expand Up @@ -915,7 +915,7 @@ internal void SerializeSceneObject(NetworkWriter writer, ulong targetClientId)
writer.WriteBool(IsSceneObject ?? true);

// Write the hash for this NetworkObject
writer.WriteUInt32Packed(GlobalObjectIdHash);
writer.WriteUInt32Packed(HostCheckForGlobalObjectIdHashOverride());

if (IncludeTransformWhenSpawning == null || IncludeTransformWhenSpawning(OwnerClientId))
{
Expand Down Expand Up @@ -1054,5 +1054,30 @@ internal static NetworkObject DeserializeSceneObject(NetworkBuffer objectStream,

return networkObject;
}

/// <summary>
/// Only applies to Host mode.
/// Will return the registered source NetworkPrefab's GlobalObjectIdHash if one exists.
/// Server and Clients will always return the NetworkObject's GlobalObjectIdHash.
/// </summary>
/// <returns></returns>
internal uint HostCheckForGlobalObjectIdHashOverride()
{
if (NetworkManager.IsHost)
{
if (NetworkManager.PrefabHandler.ContainsHandler(this))
{
var globalObjectIdHash = NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash);
return globalObjectIdHash == 0 ? GlobalObjectIdHash : globalObjectIdHash;
}
else
if (NetworkManager.NetworkConfig.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash))
{
return NetworkManager.NetworkConfig.OverrideToNetworkPrefab[GlobalObjectIdHash];
}
}

return GlobalObjectIdHash;
}
}
}
Loading