com.unity.netcode.gameobjects@1.0.0-pre.8
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.0.0-pre.8] - 2022-04-27 ### Changed - `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy<T>`. (#1901) ### Removed - Removed `SIPTransport` (#1870) - Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs). ### Fixed - Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890) - Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884) - Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883) - Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854) - Passing generic types to RPCs no longer causes a native crash (#1901) - Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)
This commit is contained in:
65
Runtime/Core/ComponentFactory.cs
Normal file
65
Runtime/Core/ComponentFactory.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.Netcode
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to support testable code by allowing any supported component used by NetworkManager to be replaced
|
||||
/// with a mock component or a test version that overloads certain methods to change or record their behavior.
|
||||
/// Components currently supported by ComponentFactory:
|
||||
/// - IDeferredMessageManager
|
||||
/// </summary>
|
||||
internal static class ComponentFactory
|
||||
{
|
||||
internal delegate object CreateObjectDelegate(NetworkManager networkManager);
|
||||
|
||||
private static Dictionary<Type, CreateObjectDelegate> s_Delegates = new Dictionary<Type, CreateObjectDelegate>();
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates an instance of a given interface
|
||||
/// </summary>
|
||||
/// <param name="networkManager">The network manager</param>
|
||||
/// <typeparam name="T">The interface to instantiate it with</typeparam>
|
||||
/// <returns></returns>
|
||||
public static T Create<T>(NetworkManager networkManager)
|
||||
{
|
||||
return (T)s_Delegates[typeof(T)](networkManager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the default creation logic for a given interface type
|
||||
/// </summary>
|
||||
/// <param name="creator">The factory delegate to create the instance</param>
|
||||
/// <typeparam name="T">The interface type to override</typeparam>
|
||||
public static void Register<T>(CreateObjectDelegate creator)
|
||||
{
|
||||
s_Delegates[typeof(T)] = creator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverts the creation logic for a given interface type to the default logic
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The interface type to revert</typeparam>
|
||||
public static void Deregister<T>()
|
||||
{
|
||||
s_Delegates.Remove(typeof(T));
|
||||
SetDefaults();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the default creation logic for all supported component types
|
||||
/// </summary>
|
||||
public static void SetDefaults()
|
||||
{
|
||||
SetDefault<IDeferredMessageManager>(networkManager => new DeferredMessageManager(networkManager));
|
||||
}
|
||||
|
||||
private static void SetDefault<T>(CreateObjectDelegate creator)
|
||||
{
|
||||
if (!s_Delegates.ContainsKey(typeof(T)))
|
||||
{
|
||||
s_Delegates[typeof(T)] = creator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Core/ComponentFactory.cs.meta
Normal file
3
Runtime/Core/ComponentFactory.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fda4c0eb89644fcea5416bbf98ea0ba0
|
||||
timeCreated: 1649966562
|
||||
@@ -122,7 +122,7 @@ namespace Unity.Netcode
|
||||
return !m_NetworkManager.m_StopProcessingMessages;
|
||||
}
|
||||
|
||||
public bool OnVerifyCanReceive(ulong senderId, Type messageType)
|
||||
public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReader messageContent, ref NetworkContext context)
|
||||
{
|
||||
if (m_NetworkManager.PendingClients.TryGetValue(senderId, out PendingClient client) &&
|
||||
(client.ConnectionState == PendingClient.State.PendingApproval || (client.ConnectionState == PendingClient.State.PendingConnection && messageType != typeof(ConnectionRequestMessage))))
|
||||
@@ -223,6 +223,8 @@ namespace Unity.Netcode
|
||||
/// </summary>
|
||||
public NetworkSpawnManager SpawnManager { get; private set; }
|
||||
|
||||
internal IDeferredMessageManager DeferredMessageManager { get; private set; }
|
||||
|
||||
public CustomMessagingManager CustomMessagingManager { get; private set; }
|
||||
|
||||
public NetworkSceneManager SceneManager { get; private set; }
|
||||
@@ -484,6 +486,253 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Adds a new prefab to the network prefab list.
|
||||
/// This can be any GameObject with a NetworkObject component, from any source (addressables, asset
|
||||
/// bundles, Resource.Load, dynamically created, etc)
|
||||
///
|
||||
/// There are three limitations to this method:
|
||||
/// - If you have NetworkConfig.ForceSamePrefabs enabled, you can only do this before starting
|
||||
/// networking, and the server and all connected clients must all have the same exact set of prefabs
|
||||
/// added via this method before connecting
|
||||
/// - Adding a prefab on the server does not automatically add it on the client - it's up to you
|
||||
/// to make sure the client and server are synchronized via whatever method makes sense for your game
|
||||
/// (RPCs, configs, deterministic loading, etc)
|
||||
/// - If the server sends a Spawn message to a client that has not yet added a prefab for, the spawn message
|
||||
/// and any other relevant messages will be held for a configurable time (default 1 second, configured via
|
||||
/// NetworkConfig.SpawnTimeout) before an error is logged. This is intented to enable the SDK to gracefully
|
||||
/// handle unexpected conditions (slow disks, slow network, etc) that slow down asset loading. This timeout
|
||||
/// should not be relied on and code shouldn't be written around it - your code should be written so that
|
||||
/// the asset is expected to be loaded before it's needed.
|
||||
/// </summary>
|
||||
/// <param name="prefab"></param>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public void AddNetworkPrefab(GameObject prefab)
|
||||
{
|
||||
if (IsListening && NetworkConfig.ForceSamePrefabs)
|
||||
{
|
||||
throw new Exception($"All prefabs must be registered before starting {nameof(NetworkManager)} when {nameof(NetworkConfig.ForceSamePrefabs)} is enabled.");
|
||||
}
|
||||
|
||||
var networkObject = prefab.GetComponent<NetworkObject>();
|
||||
if (!networkObject)
|
||||
{
|
||||
throw new Exception($"All {nameof(NetworkPrefab)}s must contain a {nameof(NetworkObject)} component.");
|
||||
}
|
||||
|
||||
var networkPrefab = new NetworkPrefab { Prefab = prefab };
|
||||
NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
if (IsListening)
|
||||
{
|
||||
var sourcePrefabGlobalObjectIdHash = (uint)0;
|
||||
var targetPrefabGlobalObjectIdHash = (uint)0;
|
||||
if (!ShouldAddPrefab(networkPrefab, out sourcePrefabGlobalObjectIdHash, out targetPrefabGlobalObjectIdHash))
|
||||
{
|
||||
NetworkConfig.NetworkPrefabs.Remove(networkPrefab);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AddPrefabRegistration(networkPrefab, sourcePrefabGlobalObjectIdHash, targetPrefabGlobalObjectIdHash))
|
||||
{
|
||||
NetworkConfig.NetworkPrefabs.Remove(networkPrefab);
|
||||
return;
|
||||
}
|
||||
DeferredMessageManager.ProcessTriggers(IDeferredMessageManager.TriggerType.OnAddPrefab, networkObject.GlobalObjectIdHash);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldAddPrefab(NetworkPrefab networkPrefab, out uint sourcePrefabGlobalObjectIdHash, out uint targetPrefabGlobalObjectIdHash, int index = -1)
|
||||
{
|
||||
sourcePrefabGlobalObjectIdHash = 0;
|
||||
targetPrefabGlobalObjectIdHash = 0;
|
||||
var networkObject = (NetworkObject)null;
|
||||
if (networkPrefab == null || (networkPrefab.Prefab == null && networkPrefab.Override == NetworkPrefabOverride.None))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
$"{nameof(NetworkPrefab)} cannot be null ({nameof(NetworkPrefab)} at index: {index})");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (networkPrefab.Override == NetworkPrefabOverride.None)
|
||||
{
|
||||
networkObject = networkPrefab.Prefab.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{PrefabDebugHelper(networkPrefab)} is missing " +
|
||||
$"a {nameof(NetworkObject)} component (entry will be ignored).");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise get the GlobalObjectIdHash value
|
||||
sourcePrefabGlobalObjectIdHash = networkObject.GlobalObjectIdHash;
|
||||
}
|
||||
else // Validate Overrides
|
||||
{
|
||||
// Validate source prefab override values first
|
||||
switch (networkPrefab.Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
if (networkPrefab.SourceHashToOverride == 0)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.SourceHashToOverride)} is zero " +
|
||||
"(entry will be ignored).");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
sourcePrefabGlobalObjectIdHash = networkPrefab.SourceHashToOverride;
|
||||
break;
|
||||
}
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
if (networkPrefab.SourcePrefabToOverride == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.SourcePrefabToOverride)} is null (entry will be ignored).");
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry {networkPrefab.SourceHashToOverride} will be removed and ignored.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
networkObject = networkPrefab.SourcePrefabToOverride.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} ({networkPrefab.SourcePrefabToOverride.name}) " +
|
||||
$"is missing a {nameof(NetworkObject)} component (entry will be ignored).");
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry (\"{networkPrefab.SourcePrefabToOverride.name}\") will be removed and ignored.");
|
||||
return false;
|
||||
}
|
||||
|
||||
sourcePrefabGlobalObjectIdHash = networkObject.GlobalObjectIdHash;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate target prefab override values next
|
||||
if (networkPrefab.OverridingTargetPrefab == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.OverridingTargetPrefab)} is null!");
|
||||
}
|
||||
switch (networkPrefab.Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry {networkPrefab.SourceHashToOverride} will be removed and ignored.");
|
||||
break;
|
||||
}
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry ({networkPrefab.SourcePrefabToOverride.name}) will be removed and ignored.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPrefabGlobalObjectIdHash = networkPrefab.OverridingTargetPrefab.GetComponent<NetworkObject>().GlobalObjectIdHash;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool AddPrefabRegistration(NetworkPrefab networkPrefab, uint sourcePrefabGlobalObjectIdHash, uint targetPrefabGlobalObjectIdHash)
|
||||
{
|
||||
// Assign the appropriate GlobalObjectIdHash to the appropriate NetworkPrefab
|
||||
if (!NetworkConfig.NetworkPrefabOverrideLinks.ContainsKey(sourcePrefabGlobalObjectIdHash))
|
||||
{
|
||||
if (networkPrefab.Override == NetworkPrefabOverride.None)
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, networkPrefab);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!NetworkConfig.OverrideToNetworkPrefab.ContainsKey(targetPrefabGlobalObjectIdHash))
|
||||
{
|
||||
switch (networkPrefab.Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, networkPrefab);
|
||||
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
|
||||
}
|
||||
break;
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, networkPrefab);
|
||||
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var networkObject = networkPrefab.Prefab.GetComponent<NetworkObject>();
|
||||
// This can happen if a user tries to make several GlobalObjectIdHash values point to the same target
|
||||
Debug.LogError($"{nameof(NetworkPrefab)} (\"{networkObject.name}\") has a duplicate {nameof(NetworkObject.GlobalObjectIdHash)} target entry value of: {targetPrefabGlobalObjectIdHash}! Removing entry from list!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var networkObject = networkPrefab.Prefab.GetComponent<NetworkObject>();
|
||||
// This should never happen, but in the case it somehow does log an error and remove the duplicate entry
|
||||
Debug.LogError($"{nameof(NetworkPrefab)} ({networkObject.name}) has a duplicate {nameof(NetworkObject.GlobalObjectIdHash)} source entry value of: {sourcePrefabGlobalObjectIdHash}! Removing entry from list!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializePrefabs(int startIdx = 0)
|
||||
{
|
||||
// This is used to remove entries not needed or invalid
|
||||
var removeEmptyPrefabs = new List<int>();
|
||||
|
||||
// Build the NetworkPrefabOverrideLinks dictionary
|
||||
for (int i = startIdx; i < NetworkConfig.NetworkPrefabs.Count; i++)
|
||||
{
|
||||
var sourcePrefabGlobalObjectIdHash = (uint)0;
|
||||
var targetPrefabGlobalObjectIdHash = (uint)0;
|
||||
if (!ShouldAddPrefab(NetworkConfig.NetworkPrefabs[i], out sourcePrefabGlobalObjectIdHash, out targetPrefabGlobalObjectIdHash, i))
|
||||
{
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!AddPrefabRegistration(NetworkConfig.NetworkPrefabs[i], sourcePrefabGlobalObjectIdHash, targetPrefabGlobalObjectIdHash))
|
||||
{
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out anything that is invalid or not used (for invalid entries we already logged warnings to the user earlier)
|
||||
// Iterate backwards so indices don't shift as we remove
|
||||
for (int i = removeEmptyPrefabs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
NetworkConfig.NetworkPrefabs.RemoveAt(removeEmptyPrefabs[i]);
|
||||
}
|
||||
|
||||
removeEmptyPrefabs.Clear();
|
||||
}
|
||||
|
||||
private void Initialize(bool server)
|
||||
{
|
||||
@@ -494,6 +743,8 @@ namespace Unity.Netcode
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentFactory.SetDefaults();
|
||||
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
NetworkLog.LogInfo(nameof(Initialize));
|
||||
@@ -524,6 +775,8 @@ namespace Unity.Netcode
|
||||
// Create spawn manager instance
|
||||
SpawnManager = new NetworkSpawnManager(this);
|
||||
|
||||
DeferredMessageManager = ComponentFactory.Create<IDeferredMessageManager>(this);
|
||||
|
||||
CustomMessagingManager = new CustomMessagingManager(this);
|
||||
|
||||
SceneManager = new NetworkSceneManager(this);
|
||||
@@ -573,171 +826,11 @@ namespace Unity.Netcode
|
||||
|
||||
this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate);
|
||||
|
||||
// This is used to remove entries not needed or invalid
|
||||
var removeEmptyPrefabs = new List<int>();
|
||||
|
||||
// Always clear our prefab override links before building
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Clear();
|
||||
NetworkConfig.OverrideToNetworkPrefab.Clear();
|
||||
|
||||
// Build the NetworkPrefabOverrideLinks dictionary
|
||||
for (int i = 0; i < NetworkConfig.NetworkPrefabs.Count; i++)
|
||||
{
|
||||
var sourcePrefabGlobalObjectIdHash = (uint)0;
|
||||
var targetPrefabGlobalObjectIdHash = (uint)0;
|
||||
var networkObject = (NetworkObject)null;
|
||||
if (NetworkConfig.NetworkPrefabs[i] == null || (NetworkConfig.NetworkPrefabs[i].Prefab == null && NetworkConfig.NetworkPrefabs[i].Override == NetworkPrefabOverride.None))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
$"{nameof(NetworkPrefab)} cannot be null ({nameof(NetworkPrefab)} at index: {i})");
|
||||
}
|
||||
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
else if (NetworkConfig.NetworkPrefabs[i].Override == NetworkPrefabOverride.None)
|
||||
{
|
||||
var networkPrefab = NetworkConfig.NetworkPrefabs[i];
|
||||
networkObject = networkPrefab.Prefab.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{PrefabDebugHelper(networkPrefab)} is missing " +
|
||||
$"a {nameof(NetworkObject)} component (entry will be ignored).");
|
||||
}
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise get the GlobalObjectIdHash value
|
||||
sourcePrefabGlobalObjectIdHash = networkObject.GlobalObjectIdHash;
|
||||
}
|
||||
else // Validate Overrides
|
||||
{
|
||||
// Validate source prefab override values first
|
||||
switch (NetworkConfig.NetworkPrefabs[i].Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
if (NetworkConfig.NetworkPrefabs[i].SourceHashToOverride == 0)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.SourceHashToOverride)} is zero " +
|
||||
"(entry will be ignored).");
|
||||
}
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
sourcePrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].SourceHashToOverride;
|
||||
break;
|
||||
}
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
if (NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.SourcePrefabToOverride)} is null (entry will be ignored).");
|
||||
}
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry {NetworkConfig.NetworkPrefabs[i].SourceHashToOverride} will be removed and ignored.");
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
networkObject = NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} ({NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.name}) " +
|
||||
$"is missing a {nameof(NetworkObject)} component (entry will be ignored).");
|
||||
}
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry (\"{NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.name}\") will be removed and ignored.");
|
||||
removeEmptyPrefabs.Add(i);
|
||||
continue;
|
||||
}
|
||||
sourcePrefabGlobalObjectIdHash = networkObject.GlobalObjectIdHash;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate target prefab override values next
|
||||
if (NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
|
||||
{
|
||||
NetworkLog.LogWarning($"{nameof(NetworkPrefab)} {nameof(NetworkPrefab.OverridingTargetPrefab)} is null!");
|
||||
}
|
||||
removeEmptyPrefabs.Add(i);
|
||||
switch (NetworkConfig.NetworkPrefabs[i].Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry {NetworkConfig.NetworkPrefabs[i].SourceHashToOverride} will be removed and ignored.");
|
||||
break;
|
||||
}
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
Debug.LogWarning($"{nameof(NetworkPrefab)} override entry ({NetworkConfig.NetworkPrefabs[i].SourcePrefabToOverride.name}) will be removed and ignored.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPrefabGlobalObjectIdHash = NetworkConfig.NetworkPrefabs[i].OverridingTargetPrefab.GetComponent<NetworkObject>().GlobalObjectIdHash;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the appropriate GlobalObjectIdHash to the appropriate NetworkPrefab
|
||||
if (!NetworkConfig.NetworkPrefabOverrideLinks.ContainsKey(sourcePrefabGlobalObjectIdHash))
|
||||
{
|
||||
if (NetworkConfig.NetworkPrefabs[i].Override == NetworkPrefabOverride.None)
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!NetworkConfig.OverrideToNetworkPrefab.ContainsKey(targetPrefabGlobalObjectIdHash))
|
||||
{
|
||||
switch (NetworkConfig.NetworkPrefabs[i].Override)
|
||||
{
|
||||
case NetworkPrefabOverride.Prefab:
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);
|
||||
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
|
||||
}
|
||||
break;
|
||||
case NetworkPrefabOverride.Hash:
|
||||
{
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Add(sourcePrefabGlobalObjectIdHash, NetworkConfig.NetworkPrefabs[i]);
|
||||
NetworkConfig.OverrideToNetworkPrefab.Add(targetPrefabGlobalObjectIdHash, sourcePrefabGlobalObjectIdHash);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This can happen if a user tries to make several GlobalObjectIdHash values point to the same target
|
||||
Debug.LogError($"{nameof(NetworkPrefab)} (\"{networkObject.name}\") has a duplicate {nameof(NetworkObject.GlobalObjectIdHash)} target entry value of: {targetPrefabGlobalObjectIdHash}! Removing entry from list!");
|
||||
removeEmptyPrefabs.Add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This should never happen, but in the case it somehow does log an error and remove the duplicate entry
|
||||
Debug.LogError($"{nameof(NetworkPrefab)} ({networkObject.name}) has a duplicate {nameof(NetworkObject.GlobalObjectIdHash)} source entry value of: {sourcePrefabGlobalObjectIdHash}! Removing entry from list!");
|
||||
removeEmptyPrefabs.Add(i);
|
||||
}
|
||||
}
|
||||
InitializePrefabs();
|
||||
|
||||
// If we have a player prefab, then we need to verify it is in the list of NetworkPrefabOverrideLinks for client side spawning.
|
||||
if (NetworkConfig.PlayerPrefab != null)
|
||||
@@ -764,15 +857,6 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out anything that is invalid or not used (for invalid entries we already logged warnings to the user earlier)
|
||||
// Iterate backwards so indices don't shift as we remove
|
||||
for (int i = removeEmptyPrefabs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
NetworkConfig.NetworkPrefabs.RemoveAt(removeEmptyPrefabs[i]);
|
||||
}
|
||||
|
||||
removeEmptyPrefabs.Clear();
|
||||
|
||||
NetworkConfig.NetworkTransport.OnTransportEvent += HandleRawTransportPoll;
|
||||
|
||||
NetworkConfig.NetworkTransport.Initialize(this);
|
||||
@@ -930,7 +1014,9 @@ namespace Unity.Netcode
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetworkConfig.ConnectionApproval)
|
||||
// Only if it is starting as a server or host do we need to check this
|
||||
// Clients don't invoke the ConnectionApprovalCallback
|
||||
if (NetworkConfig.ConnectionApproval && type != StartType.Client)
|
||||
{
|
||||
if (ConnectionApprovalCallback == null)
|
||||
{
|
||||
@@ -985,6 +1071,7 @@ namespace Unity.Netcode
|
||||
private void Awake()
|
||||
{
|
||||
UnityEngine.SceneManagement.SceneManager.sceneUnloaded += OnSceneUnloaded;
|
||||
NetworkVariableHelper.InitializeAllBaseDelegates();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1081,8 +1168,13 @@ namespace Unity.Netcode
|
||||
NetworkLog.LogInfo(nameof(Shutdown));
|
||||
}
|
||||
|
||||
m_ShuttingDown = true;
|
||||
m_StopProcessingMessages = discardMessageQueue;
|
||||
// If we're not running, don't start shutting down, it would only cause an immediate
|
||||
// shutdown the next time the manager is started.
|
||||
if (IsServer || IsClient)
|
||||
{
|
||||
m_ShuttingDown = true;
|
||||
m_StopProcessingMessages = discardMessageQueue;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ShutdownInternal()
|
||||
@@ -1165,13 +1257,17 @@ namespace Unity.Netcode
|
||||
|
||||
if (SpawnManager != null)
|
||||
{
|
||||
SpawnManager.CleanupAllTriggers();
|
||||
SpawnManager.DespawnAndDestroyNetworkObjects();
|
||||
SpawnManager.ServerResetShudownStateForSceneObjects();
|
||||
|
||||
SpawnManager = null;
|
||||
}
|
||||
|
||||
if (DeferredMessageManager != null)
|
||||
{
|
||||
DeferredMessageManager.CleanupAllTriggers();
|
||||
}
|
||||
|
||||
if (SceneManager != null)
|
||||
{
|
||||
// Let the NetworkSceneManager clean up its two SceneEvenData instances
|
||||
@@ -1287,7 +1383,7 @@ namespace Unity.Netcode
|
||||
|
||||
NetworkObject.VerifyParentingStatus();
|
||||
}
|
||||
SpawnManager.CleanupStaleTriggers();
|
||||
DeferredMessageManager.CleanupStaleTriggers();
|
||||
|
||||
if (m_ShuttingDown)
|
||||
{
|
||||
@@ -1415,11 +1511,6 @@ namespace Unity.Netcode
|
||||
break;
|
||||
case NetworkEvent.Data:
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
NetworkLog.LogInfo($"Incoming Data From {clientId}: {payload.Count} bytes");
|
||||
}
|
||||
|
||||
clientId = TransportIdToClientId(clientId);
|
||||
|
||||
HandleIncomingData(clientId, payload, receiveTime);
|
||||
@@ -1444,7 +1535,11 @@ namespace Unity.Netcode
|
||||
}
|
||||
else
|
||||
{
|
||||
Shutdown();
|
||||
// We must pass true here and not process any sends messages
|
||||
// as we are no longer connected and thus there is no one to
|
||||
// send any messages to and this will cause an exception within
|
||||
// UnityTransport as the client ID is no longer valid.
|
||||
Shutdown(true);
|
||||
}
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
s_TransportDisconnect.End();
|
||||
|
||||
@@ -826,7 +826,7 @@ namespace Unity.Netcode
|
||||
|
||||
internal struct SceneObject
|
||||
{
|
||||
public struct HeaderData
|
||||
public struct HeaderData : INetworkSerializeByMemcpy
|
||||
{
|
||||
public ulong NetworkObjectId;
|
||||
public ulong OwnerClientId;
|
||||
@@ -845,7 +845,7 @@ namespace Unity.Netcode
|
||||
public ulong ParentObjectId;
|
||||
|
||||
//If(Metadata.HasTransform)
|
||||
public struct TransformData
|
||||
public struct TransformData : INetworkSerializeByMemcpy
|
||||
{
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
|
||||
Reference in New Issue
Block a user