com.unity.netcode.gameobjects@2.0.0-pre.3
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). ## [2.0.0-pre.3] - 2024-07-23 ### Added - Added: `UnityTransport.GetNetworkDriver` and `UnityTransport.GetLocalEndpoint` methods to expose the driver and local endpoint being used. (#2978) ### Fixed - Fixed issue where deferred despawn was causing GC allocations when converting an `IEnumerable` to a list. (#2983) - Fixed issue where the realtime network stats monitor was not able to display RPC traffic in release builds due to those stats being only available in development builds or the editor. (#2979) - Fixed issue where `NetworkManager.ScenesLoaded` was not being updated if `PostSynchronizationSceneUnloading` was set and any loaded scenes not used during synchronization were unloaded. (#2971) - Fixed issue where `Rigidbody2d` under Unity 6000.0.11f1 has breaking changes where `velocity` is now `linearVelocity` and `isKinematic` is replaced by `bodyType`. (#2971) - Fixed issue where `NetworkSpawnManager.InstantiateAndSpawn` and `NetworkObject.InstantiateAndSpawn` were not honoring the ownerClientId parameter when using a client-server network topology. (#2968) - Fixed issue where internal delta serialization could not have a byte serializer defined when serializing deltas for other types. Added `[GenerateSerializationForType(typeof(byte))]` to both the `NetworkVariable` and `AnticipatedNetworkVariable` classes to assure a byte serializer is defined.(#2962) - Fixed issue when scene management was disabled and the session owner would still try to synchronize a late joining client. (#2962) - Fixed issue when using a distributed authority network topology where it would allow a session owner to spawn a `NetworkObject` prior to being approved. Now, an error message is logged and the `NetworkObject` will not be spawned prior to the client being approved. (#2962) - Fixed issue where attempting to spawn during `NetworkBehaviour.OnInSceneObjectsSpawned` and `NetworkBehaviour.OnNetworkSessionSynchronized` notifications would throw a collection modified exception. (#2962) ### Changed - Changed logic where clients can now set the `NetworkSceneManager` client synchronization mode when using a distributed authority network topology. (#2985)
This commit is contained in:
@@ -15,7 +15,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The base class to override to write network code. Inherits MonoBehaviour
|
||||
/// The base class to override to write network code. Inherits MonoBehaviour.
|
||||
/// </summary>
|
||||
public abstract class NetworkBehaviour : MonoBehaviour
|
||||
{
|
||||
@@ -27,7 +27,7 @@ namespace Unity.Netcode
|
||||
// RuntimeAccessModifiersILPP will make this `public`
|
||||
internal static readonly Dictionary<Type, Dictionary<uint, RpcReceiveHandler>> __rpc_func_table = new Dictionary<Type, Dictionary<uint, RpcReceiveHandler>>();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
// RuntimeAccessModifiersILPP will make this `public`
|
||||
internal static readonly Dictionary<Type, Dictionary<uint, string>> __rpc_name_table = new Dictionary<Type, Dictionary<uint, string>>();
|
||||
#endif
|
||||
@@ -124,7 +124,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
if (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
NetworkManager.NetworkMetrics.TrackRpcSent(
|
||||
@@ -252,7 +252,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
if (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
if (clientRpcParams.Send.TargetClientIds != null)
|
||||
@@ -410,8 +410,8 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the NetworkManager that owns this NetworkBehaviour instance
|
||||
/// See note around `NetworkObject` for how there is a chicken / egg problem when we are not initialized
|
||||
/// Gets the NetworkManager that owns this NetworkBehaviour instance.
|
||||
/// See `NetworkObject` note for how there is a chicken/egg problem when not initialized.
|
||||
/// </summary>
|
||||
public NetworkManager NetworkManager
|
||||
{
|
||||
@@ -439,38 +439,40 @@ namespace Unity.Netcode
|
||||
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeArray{ulong})"/>,
|
||||
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeList{ulong})"/>,
|
||||
/// <see cref="Unity.Netcode.RpcTarget.Not(ulong[])"/>, and
|
||||
/// <see cref="Unity.Netcode.RpcTarget.Not{T}(T)"/>
|
||||
/// <see cref="Unity.Netcode.RpcTarget.Not{T}(T)"/>.
|
||||
/// </summary>
|
||||
#pragma warning restore IDE0001
|
||||
public RpcTarget RpcTarget => NetworkManager.RpcTarget;
|
||||
|
||||
/// <summary>
|
||||
/// If a NetworkObject is assigned, it will return whether or not this NetworkObject
|
||||
/// is the local player object. If no NetworkObject is assigned it will always return false.
|
||||
/// If a NetworkObject is assigned, returns whether the NetworkObject
|
||||
/// is the local player object. If no NetworkObject is assigned, returns false.
|
||||
/// </summary>
|
||||
public bool IsLocalPlayer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the object is owned by the local player or if the object is the local player object
|
||||
/// Gets whether the object is owned by the local player or if the object is the local player object.
|
||||
/// </summary>
|
||||
public bool IsOwner { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if we are executing as server
|
||||
/// Gets whether executing as a server.
|
||||
/// </summary>
|
||||
public bool IsServer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the local client has authority over the associated NetworkObject
|
||||
/// Client-Server: This will return true if IsServer or IsHost
|
||||
/// Distributed Authority: This will return true if IsOwner
|
||||
/// Determines if the local client has authority over the associated NetworkObject.
|
||||
/// <list type="bullet">
|
||||
/// <item>In client-server contexts: returns true if `IsServer` or `IsHost`.</item>
|
||||
/// <item>In distributed authority contexts: returns true if `IsOwner`.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public bool HasAuthority { get; internal set; }
|
||||
|
||||
internal NetworkClient LocalClient { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the client is the distributed authority mode session owner
|
||||
/// Gets whether the client is the distributed authority mode session owner.
|
||||
/// </summary>
|
||||
public bool IsSessionOwner
|
||||
{
|
||||
@@ -486,29 +488,29 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the server (local or remote) is a host - i.e., also a client
|
||||
/// Gets whether the server (local or remote) is a host.
|
||||
/// </summary>
|
||||
public bool ServerIsHost { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if we are executing as client
|
||||
/// Gets whether executing as a client.
|
||||
/// </summary>
|
||||
public bool IsClient { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets if we are executing as Host, I.E Server and Client
|
||||
/// Gets whether executing as a host (both server and client).
|
||||
/// </summary>
|
||||
public bool IsHost { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Whether or not the object has a owner
|
||||
/// Gets whether the object has an owner.
|
||||
/// </summary>
|
||||
public bool IsOwnedByServer { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine if it is safe to access NetworkObject and NetworkManager from within a NetworkBehaviour component
|
||||
/// Primarily useful when checking NetworkObject/NetworkManager properties within FixedUpate
|
||||
/// Determines whether it's safe to access a NetworkObject and NetworkManager from within a NetworkBehaviour component.
|
||||
/// Primarily useful when checking NetworkObject or NetworkManager properties within FixedUpate.
|
||||
/// </summary>
|
||||
public bool IsSpawned { get; internal set; }
|
||||
|
||||
@@ -528,7 +530,7 @@ namespace Unity.Netcode
|
||||
/// the warning below. This is why IsBehaviourEditable had to be created. Matt was going to re-do
|
||||
/// how NetworkObject works but it was close to the release and too risky to change
|
||||
/// <summary>
|
||||
/// Gets the NetworkObject that owns this NetworkBehaviour instance
|
||||
/// Gets the NetworkObject that owns this NetworkBehaviour instance.
|
||||
/// </summary>
|
||||
public NetworkObject NetworkObject
|
||||
{
|
||||
@@ -567,19 +569,19 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this NetworkBehaviour instance has a NetworkObject owner.
|
||||
/// Gets whether this NetworkBehaviour instance has a NetworkObject owner.
|
||||
/// </summary>
|
||||
public bool HasNetworkObject => NetworkObject != null;
|
||||
|
||||
private NetworkObject m_NetworkObject = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the NetworkId of the NetworkObject that owns this NetworkBehaviour
|
||||
/// Gets the NetworkId of the NetworkObject that owns this NetworkBehaviour instance.
|
||||
/// </summary>
|
||||
public ulong NetworkObjectId { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets NetworkId for this NetworkBehaviour from the owner NetworkObject
|
||||
/// Gets NetworkId for this NetworkBehaviour from the owner NetworkObject.
|
||||
/// </summary>
|
||||
public ushort NetworkBehaviourId { get; internal set; }
|
||||
|
||||
@@ -589,7 +591,7 @@ namespace Unity.Netcode
|
||||
internal ushort NetworkBehaviourIdCache = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a the NetworkBehaviour with a given BehaviourId for the current NetworkObject
|
||||
/// Returns the NetworkBehaviour with a given BehaviourId for the current NetworkObject.
|
||||
/// </summary>
|
||||
/// <param name="behaviourId">The behaviourId to return</param>
|
||||
/// <returns>Returns NetworkBehaviour with given behaviourId</returns>
|
||||
@@ -599,7 +601,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ClientId that owns the NetworkObject
|
||||
/// Gets the ClientId that owns this NetworkObject.
|
||||
/// </summary>
|
||||
public ulong OwnerClientId { get; internal set; }
|
||||
|
||||
@@ -651,28 +653,29 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Distributed Authority Mode Only
|
||||
/// Only for use in distributed authority mode.
|
||||
/// Invoked only on the authority instance when a <see cref="NetworkObject"/> is deferring its despawn on non-authoritative instances.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See also: <see cref="NetworkObject.DeferDespawn(int, bool)"/>
|
||||
/// </remarks>
|
||||
/// <param name="despawnTick">the future network tick that the <see cref="NetworkObject"/> will be despawned on non-authoritative instances</param>
|
||||
/// <param name="despawnTick">The future network tick that the <see cref="NetworkObject"/> will be despawned on non-authoritative instances</param>
|
||||
public virtual void OnDeferringDespawn(int despawnTick) { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets called after the <see cref="NetworkObject"/> is spawned. No NetworkBehaviours associated with the NetworkObject will have had <see cref="OnNetworkSpawn"/> invoked yet.
|
||||
/// A reference to <see cref="NetworkManager"/> is passed in as a parameter to determine the context of execution (IsServer/IsClient)
|
||||
/// A reference to <see cref="NetworkManager"/> is passed in as a parameter to determine the context of execution (`IsServer` or `IsClient`).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <param name="networkManager">a ref to the <see cref="NetworkManager"/> since this is not yet set on the <see cref="NetworkBehaviour"/></param>
|
||||
/// <remarks>
|
||||
/// The <see cref="NetworkBehaviour"/> will not have anything assigned to it at this point in time.
|
||||
/// Settings like ownership, NetworkBehaviourId, NetworkManager, and most other spawn related properties will not be set.
|
||||
/// This can be used to handle things like initializing/instantiating a NetworkVariable or the like.
|
||||
/// Settings like ownership, NetworkBehaviourId, NetworkManager, and most other spawn-related properties will not be set.
|
||||
/// This can be used to handle things like initializing a NetworkVariable.
|
||||
/// </remarks>
|
||||
protected virtual void OnNetworkPreSpawn(ref NetworkManager networkManager) { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the <see cref="NetworkObject"/> gets spawned, message handlers are ready to be registered and the network is setup.
|
||||
/// Gets called when the <see cref="NetworkObject"/> gets spawned, message handlers are ready to be registered, and the network is set up.
|
||||
/// </summary>
|
||||
public virtual void OnNetworkSpawn() { }
|
||||
|
||||
@@ -686,28 +689,28 @@ namespace Unity.Netcode
|
||||
protected virtual void OnNetworkPostSpawn() { }
|
||||
|
||||
/// <summary>
|
||||
/// [Client-Side Only]
|
||||
/// When a new client joins it is synchronized with all spawned NetworkObjects and scenes loaded for the session joined. At the end of the synchronization process, when all
|
||||
/// This method is only available client-side.
|
||||
/// When a new client joins it's synchronized with all spawned NetworkObjects and scenes loaded for the session joined. At the end of the synchronization process, when all
|
||||
/// <see cref="NetworkObject"/>s and scenes (if scene management is enabled) have finished synchronizing, all NetworkBehaviour components associated with spawned <see cref="NetworkObject"/>s
|
||||
/// will have this method invoked.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be used to handle post synchronization actions where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
|
||||
/// This can be used to handle post-synchronization actions where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
|
||||
/// This is only invoked on clients during a client-server network topology session.
|
||||
/// </remarks>
|
||||
protected virtual void OnNetworkSessionSynchronized() { }
|
||||
|
||||
/// <summary>
|
||||
/// [Client & Server Side]
|
||||
/// When a scene is loaded an in-scene placed NetworkObjects are all spawned, this method is invoked on all of the newly spawned in-scene placed NetworkObjects.
|
||||
/// When a scene is loaded and in-scene placed NetworkObjects are finished spawning, this method is invoked on all of the newly spawned in-scene placed NetworkObjects.
|
||||
/// This method runs both client and server side.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be used to handle post scene loaded actions for in-scene placed NetworkObjcts where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
|
||||
/// This method can be used to handle post-scene loaded actions for in-scene placed NetworkObjcts where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
|
||||
/// </remarks>
|
||||
protected virtual void OnInSceneObjectsSpawned() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the <see cref="NetworkObject"/> gets despawned. Is called both on the server and clients.
|
||||
/// Gets called when the <see cref="NetworkObject"/> gets despawned. This method runs both client and server side.
|
||||
/// </summary>
|
||||
public virtual void OnNetworkDespawn() { }
|
||||
|
||||
@@ -803,7 +806,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the local client gains ownership of this object
|
||||
/// Gets called when the local client gains ownership of this object.
|
||||
/// </summary>
|
||||
public virtual void OnGainedOwnership() { }
|
||||
|
||||
@@ -814,8 +817,8 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked on all clients, override this method to be notified of any
|
||||
/// ownership changes (even if the instance was niether the previous or
|
||||
/// Invoked on all clients. Override this method to be notified of any
|
||||
/// ownership changes (even if the instance was neither the previous or
|
||||
/// newly assigned current owner).
|
||||
/// </summary>
|
||||
/// <param name="previous">the previous owner</param>
|
||||
@@ -831,7 +834,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when we loose ownership of this object
|
||||
/// Gets called when ownership of this object is lost.
|
||||
/// </summary>
|
||||
public virtual void OnLostOwnership() { }
|
||||
|
||||
@@ -842,7 +845,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the parent NetworkObject of this NetworkBehaviour's NetworkObject has changed
|
||||
/// Gets called when the parent NetworkObject of this NetworkBehaviour's NetworkObject has changed.
|
||||
/// </summary>
|
||||
/// <param name="parentNetworkObject">the new <see cref="NetworkObject"/> parent</param>
|
||||
public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { }
|
||||
@@ -877,7 +880,7 @@ namespace Unity.Netcode
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
__rpc_func_table[GetType()][hash] = handler;
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
__rpc_name_table[GetType()][hash] = rpcMethodName;
|
||||
#endif
|
||||
}
|
||||
@@ -903,7 +906,7 @@ namespace Unity.Netcode
|
||||
if (!__rpc_func_table.ContainsKey(GetType()))
|
||||
{
|
||||
__rpc_func_table[GetType()] = new Dictionary<uint, RpcReceiveHandler>();
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
__rpc_name_table[GetType()] = new Dictionary<uint, string>();
|
||||
#endif
|
||||
__initializeRpcs();
|
||||
@@ -1112,31 +1115,38 @@ namespace Unity.Netcode
|
||||
/// </remarks>
|
||||
internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClientId)
|
||||
{
|
||||
// Create any values that require accessing the NetworkManager locally (it is expensive to access it in NetworkBehaviour)
|
||||
var networkManager = NetworkManager;
|
||||
if (networkManager.DistributedAuthorityMode)
|
||||
var distributedAuthority = networkManager.DistributedAuthorityMode;
|
||||
var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety;
|
||||
|
||||
// Always write the NetworkVariable count even if zero for distributed authority (used by comb server)
|
||||
if (distributedAuthority)
|
||||
{
|
||||
writer.WriteValueSafe((ushort)NetworkVariableFields.Count);
|
||||
}
|
||||
|
||||
// Exit early if there are no NetworkVariables
|
||||
if (NetworkVariableFields.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
|
||||
// Worth either merging or more cleanly separating these codepaths.
|
||||
for (int j = 0; j < NetworkVariableFields.Count; j++)
|
||||
{
|
||||
// Note: In distributed authority mode, all clients can read
|
||||
// Client-Server: Try to write values only for clients that have read permissions.
|
||||
// Distributed Authority: All clients have read permissions, always try to write the value.
|
||||
if (NetworkVariableFields[j].CanClientRead(targetClientId))
|
||||
{
|
||||
if (networkManager.DistributedAuthorityMode)
|
||||
// Write additional NetworkVariable information when length safety is enabled or when in distributed authority mode
|
||||
if (ensureLengthSafety || distributedAuthority)
|
||||
{
|
||||
writer.WriteValueSafe(NetworkVariableFields[j].Type);
|
||||
}
|
||||
// Write the type being serialized for distributed authority (only for comb-server)
|
||||
if (distributedAuthority)
|
||||
{
|
||||
writer.WriteValueSafe(NetworkVariableFields[j].Type);
|
||||
}
|
||||
|
||||
if (networkManager.DistributedAuthorityMode || networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
{
|
||||
var writePos = writer.Position;
|
||||
// Note: This value can't be packed because we don't know how large it will be in advance
|
||||
// we reserve space for it, then write the data, then come back and fill in the space
|
||||
@@ -1148,18 +1158,19 @@ namespace Unity.Netcode
|
||||
NetworkVariableFields[j].WriteField(writer);
|
||||
var size = writer.Position - startPos;
|
||||
writer.Seek(writePos);
|
||||
// Write the NetworkVariable value
|
||||
writer.WriteValueSafe((ushort)size);
|
||||
writer.Seek(startPos + size);
|
||||
}
|
||||
else
|
||||
else // Client-Server Only: Should only ever be invoked when using a client-server NetworkTopology
|
||||
{
|
||||
// Write the NetworkVariable value
|
||||
NetworkVariableFields[j].WriteField(writer);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (ensureLengthSafety)
|
||||
{
|
||||
// Only if EnsureNetworkVariableLengthSafety, otherwise just skip
|
||||
if (networkManager.DistributedAuthorityMode || networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
// Client-Server Only: If the client cannot read this field, then skip it but write a 0 for this NetworkVariable's position
|
||||
{
|
||||
writer.WriteValueSafe((ushort)0);
|
||||
}
|
||||
@@ -1177,75 +1188,78 @@ namespace Unity.Netcode
|
||||
/// </remarks>
|
||||
internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId)
|
||||
{
|
||||
// Stack cache any values that requires accessing the NetworkManager (it is expensive to access it in NetworkBehaviour)
|
||||
var networkManager = NetworkManager;
|
||||
if (networkManager.DistributedAuthorityMode)
|
||||
var distributedAuthority = networkManager.DistributedAuthorityMode;
|
||||
var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety;
|
||||
|
||||
// Always read the NetworkVariable count when in distributed authority (sanity check if comb-server matches what client has locally)
|
||||
if (distributedAuthority)
|
||||
{
|
||||
reader.ReadValueSafe(out ushort variableCount);
|
||||
if (variableCount != NetworkVariableFields.Count)
|
||||
{
|
||||
Debug.LogError("NetworkVariable count mismatch.");
|
||||
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}] NetworkVariable count mismatch! (Read: {variableCount} vs. Expected: {NetworkVariableFields.Count})");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Exit early if nothing else to read
|
||||
if (NetworkVariableFields.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
|
||||
// Worth either merging or more cleanly separating these codepaths.
|
||||
for (int j = 0; j < NetworkVariableFields.Count; j++)
|
||||
{
|
||||
var varSize = (ushort)0;
|
||||
var readStartPos = 0;
|
||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
// Client-Server: Clients that only have read permissions will try to read the value
|
||||
// Distributed Authority: All clients have read permissions, always try to read the value
|
||||
if (NetworkVariableFields[j].CanClientRead(clientId))
|
||||
{
|
||||
reader.ReadValueSafe(out varSize);
|
||||
if (varSize == 0)
|
||||
if (ensureLengthSafety || distributedAuthority)
|
||||
{
|
||||
continue;
|
||||
// Read the type being serialized and discard it (for now) when in a distributed authority network topology (only used by comb-server)
|
||||
if (distributedAuthority)
|
||||
{
|
||||
reader.ReadValueSafe(out NetworkVariableType _);
|
||||
}
|
||||
|
||||
reader.ReadValueSafe(out varSize);
|
||||
if (varSize == 0)
|
||||
{
|
||||
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] Expected non-zero size readable NetworkVariable! (Skipping)");
|
||||
continue;
|
||||
}
|
||||
readStartPos = reader.Position;
|
||||
}
|
||||
readStartPos = reader.Position;
|
||||
}
|
||||
else // If the client cannot read this field, then skip it
|
||||
if (!NetworkVariableFields[j].CanClientRead(clientId))
|
||||
else // Client-Server Only: If the client cannot read this field, then skip it
|
||||
{
|
||||
if (networkManager.DistributedAuthorityMode)
|
||||
// If skipping and length safety, then fill in a 0 size for this one spot
|
||||
if (ensureLengthSafety)
|
||||
{
|
||||
reader.ReadValueSafe(out ushort size);
|
||||
if (size != 0)
|
||||
{
|
||||
Debug.LogError("Expected zero size");
|
||||
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] Expected zero size for non-readable NetworkVariable when EnsureNetworkVariableLengthSafety is enabled! (Skipping)");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (networkManager.DistributedAuthorityMode)
|
||||
{
|
||||
// Explicit setting of the NetworkVariableType is only needed for CMB Runtime
|
||||
reader.ReadValueSafe(out NetworkVariableType _);
|
||||
reader.ReadValueSafe(out ushort size);
|
||||
var start_marker = reader.Position;
|
||||
NetworkVariableFields[j].ReadField(reader);
|
||||
if (reader.Position - start_marker != size)
|
||||
{
|
||||
Debug.LogError("Mismatched network variable size");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkVariableFields[j].ReadField(reader);
|
||||
}
|
||||
// Read the NetworkVarible value
|
||||
NetworkVariableFields[j].ReadField(reader);
|
||||
|
||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
// When EnsureNetworkVariableLengthSafety or DistributedAuthorityMode always do a bounds check
|
||||
if (ensureLengthSafety || distributedAuthority)
|
||||
{
|
||||
if (reader.Position > (readStartPos + varSize))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning($"Var data read too far. {reader.Position - (readStartPos + varSize)} bytes.");
|
||||
NetworkLog.LogWarning($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] NetworkVariable data read too big. {reader.Position - (readStartPos + varSize)} bytes.");
|
||||
}
|
||||
|
||||
reader.Seek(readStartPos + varSize);
|
||||
@@ -1254,7 +1268,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning($"Var data read too little. {(readStartPos + varSize) - reader.Position} bytes.");
|
||||
NetworkLog.LogWarning($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] NetworkVariable data read too small. {(readStartPos + varSize) - reader.Position} bytes.");
|
||||
}
|
||||
|
||||
reader.Seek(readStartPos + varSize);
|
||||
@@ -1264,7 +1278,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local instance of a object with a given NetworkId
|
||||
/// Gets the local instance of a NetworkObject with a given NetworkId.
|
||||
/// </summary>
|
||||
/// <param name="networkId"></param>
|
||||
/// <returns></returns>
|
||||
@@ -1275,14 +1289,14 @@ namespace Unity.Netcode
|
||||
|
||||
/// <summary>
|
||||
/// Override this method if your derived NetworkBehaviour requires custom synchronization data.
|
||||
/// Note: Use of this method is only for the initial client synchronization of NetworkBehaviours
|
||||
/// Use of this method is only for the initial client synchronization of NetworkBehaviours
|
||||
/// and will increase the payload size for client synchronization and dynamically spawned
|
||||
/// <see cref="NetworkObject"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When serializing (writing) this will be invoked during the client synchronization period and
|
||||
/// When serializing (writing), this method is invoked during the client synchronization period and
|
||||
/// when spawning new NetworkObjects.
|
||||
/// When deserializing (reading), this will be invoked prior to the NetworkBehaviour's associated
|
||||
/// When deserializing (reading), this method is invoked prior to the NetworkBehaviour's associated
|
||||
/// NetworkObject being spawned.
|
||||
/// </remarks>
|
||||
/// <param name="serializer">The serializer to use to read and write the data.</param>
|
||||
@@ -1305,10 +1319,10 @@ namespace Unity.Netcode
|
||||
/// The relative client identifier targeted for the serialization of this <see cref="NetworkBehaviour"/> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value will be set prior to <see cref="OnSynchronize{T}(ref BufferSerializer{T})"/> being invoked.
|
||||
/// This value is set prior to <see cref="OnSynchronize{T}(ref BufferSerializer{T})"/> being invoked.
|
||||
/// For writing (server-side), this is useful to know which client will receive the serialized data.
|
||||
/// For reading (client-side), this will be the <see cref="NetworkManager.LocalClientId"/>.
|
||||
/// When synchronization of this instance is complete, this value will be reset to 0
|
||||
/// When synchronization of this instance is complete, this value is reset to 0.
|
||||
/// </remarks>
|
||||
protected ulong m_TargetIdBeingSynchronized { get; private set; }
|
||||
|
||||
@@ -1431,9 +1445,8 @@ namespace Unity.Netcode
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the <see cref="GameObject"/> the <see cref="NetworkBehaviour"/> is attached to.
|
||||
/// NOTE: If you override this, you will want to always invoke this base class version of this
|
||||
/// <see cref="OnDestroy"/> method!!
|
||||
/// Invoked when the <see cref="GameObject"/> the <see cref="NetworkBehaviour"/> is attached to is destroyed.
|
||||
/// If you override this, you must always invoke the base class version of this <see cref="OnDestroy"/> method.
|
||||
/// </summary>
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -29,13 +29,40 @@ namespace Unity.Netcode
|
||||
// RuntimeAccessModifiersILPP will make this `public`
|
||||
internal static readonly Dictionary<uint, RpcReceiveHandler> __rpc_func_table = new Dictionary<uint, RpcReceiveHandler>();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||
// RuntimeAccessModifiersILPP will make this `public`
|
||||
internal static readonly Dictionary<uint, string> __rpc_name_table = new Dictionary<uint, string>();
|
||||
#endif
|
||||
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
private static List<Type> s_SerializedType = new List<Type>();
|
||||
// This is used to control the serialized type not optimized messaging for integration test purposes
|
||||
internal static bool DisableNotOptimizedSerializedType;
|
||||
/// <summary>
|
||||
/// Until all serialized types are optimized for the distributed authority network topology,
|
||||
/// this will handle the notification to the user that the type being serialized is not yet
|
||||
/// optimized but will only log the message once to prevent log spamming.
|
||||
/// </summary>
|
||||
internal static void LogSerializedTypeNotOptimized<T>()
|
||||
{
|
||||
if (DisableNotOptimizedSerializedType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var type = typeof(T);
|
||||
if (!s_SerializedType.Contains(type))
|
||||
{
|
||||
s_SerializedType.Add(type);
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
Debug.LogWarning($"[{type.Name}] Serialized type has not been optimized for use with Distributed Authority!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static bool IsDistributedAuthority;
|
||||
|
||||
/// <summary>
|
||||
@@ -1062,6 +1089,13 @@ namespace Unity.Netcode
|
||||
|
||||
internal void Initialize(bool server)
|
||||
{
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (!DisableNotOptimizedSerializedType)
|
||||
{
|
||||
s_SerializedType.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if COM_UNITY_MODULES_PHYSICS
|
||||
NetworkTransformFixedUpdate.Clear();
|
||||
#endif
|
||||
@@ -1250,17 +1284,8 @@ namespace Unity.Netcode
|
||||
{
|
||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
||||
|
||||
// Notify the server that all in-scnee placed NetworkObjects are spawned at this time.
|
||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
networkObject.InternalInSceneNetworkObjectsSpawned();
|
||||
}
|
||||
|
||||
// Notify the server that everything should be synchronized/spawned at this time.
|
||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
networkObject.InternalNetworkSessionSynchronized();
|
||||
}
|
||||
SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||
OnServerStarted?.Invoke();
|
||||
ConnectionManager.LocalClient.IsApproved = true;
|
||||
return true;
|
||||
@@ -1407,17 +1432,9 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
||||
// Notify the host that all in-scnee placed NetworkObjects are spawned at this time.
|
||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
networkObject.InternalInSceneNetworkObjectsSpawned();
|
||||
}
|
||||
|
||||
// Notify the host that everything should be synchronized/spawned at this time.
|
||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
networkObject.InternalNetworkSessionSynchronized();
|
||||
}
|
||||
SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||
|
||||
OnServerStarted?.Invoke();
|
||||
OnClientStarted?.Invoke();
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Unity.Netcode
|
||||
internal uint PrefabGlobalObjectIdHash;
|
||||
|
||||
/// <summary>
|
||||
/// This is the source prefab of an in-scene placed NetworkObject. This is not set for in-scene
|
||||
/// This is the source prefab of an in-scene placed NetworkObject. This is not set for in-scene
|
||||
/// placd NetworkObjects that are not prefab instances, dynamically spawned prefab instances,
|
||||
/// or for network prefab assets.
|
||||
/// </summary>
|
||||
@@ -207,8 +207,8 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This checks to see if this NetworkObject is an in-scene placed prefab instance. If so it will
|
||||
/// automatically find the source prefab asset's GlobalObjectIdHash value, assign it to
|
||||
/// This checks to see if this NetworkObject is an in-scene placed prefab instance. If so it will
|
||||
/// automatically find the source prefab asset's GlobalObjectIdHash value, assign it to
|
||||
/// InScenePlacedSourceGlobalObjectIdHash and mark this as being in-scene placed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -540,8 +540,8 @@ namespace Unity.Netcode
|
||||
/// permission failure status codes will be returned via <see cref="OnOwnershipPermissionsFailure"/>.
|
||||
/// <see cref="Locked"/>: The <see cref="NetworkObject"/> is locked and ownership cannot be acquired.
|
||||
/// <see cref="RequestRequired"/>: The <see cref="NetworkObject"/> requires an ownership request via <see cref="RequestOwnership"/>.
|
||||
/// <see cref="RequestInProgress"/>: The <see cref="NetworkObject"/> already is processing an ownership request and ownership cannot be acquired at this time.
|
||||
/// <see cref="NotTransferrable": The <see cref="NetworkObject"/> does not have the <see cref="OwnershipStatus.Transferable"/> flag set and ownership cannot be acquired.
|
||||
/// <see cref="RequestInProgress"/>: The <see cref="NetworkObject"/> is already processing an ownership request and ownership cannot be acquired at this time.
|
||||
/// <see cref="NotTransferrable"/>: The <see cref="NetworkObject"/> does not have the <see cref="OwnershipStatus.Transferable"/> flag set and ownership cannot be acquired.
|
||||
/// </summary>
|
||||
public enum OwnershipPermissionsFailureStatus
|
||||
{
|
||||
@@ -1547,6 +1547,11 @@ namespace Unity.Netcode
|
||||
|
||||
if (NetworkManager.DistributedAuthorityMode)
|
||||
{
|
||||
if (NetworkManager.LocalClient == null || !NetworkManager.IsConnectedClient || !NetworkManager.ConnectionManager.LocalClient.IsApproved)
|
||||
{
|
||||
Debug.LogError($"Cannot spawn {name} until the client is fully connected to the session!");
|
||||
return;
|
||||
}
|
||||
if (NetworkManager.NetworkConfig.EnableSceneManagement)
|
||||
{
|
||||
NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[gameObject.scene.handle];
|
||||
@@ -1638,7 +1643,7 @@ namespace Unity.Netcode
|
||||
return null;
|
||||
}
|
||||
|
||||
ownerClientId = networkManager.DistributedAuthorityMode ? networkManager.LocalClientId : NetworkManager.ServerClientId;
|
||||
ownerClientId = networkManager.DistributedAuthorityMode ? networkManager.LocalClientId : ownerClientId;
|
||||
// We only need to check for authority when running in client-server mode
|
||||
if (!networkManager.IsServer && !networkManager.DistributedAuthorityMode)
|
||||
{
|
||||
@@ -2436,10 +2441,10 @@ namespace Unity.Netcode
|
||||
if (NetworkManager.DistributedAuthorityMode)
|
||||
{
|
||||
var readerPosition = reader.Position;
|
||||
reader.ReadValueSafe(out ushort behaviorCount);
|
||||
if (behaviorCount != ChildNetworkBehaviours.Count)
|
||||
reader.ReadValueSafe(out ushort behaviourCount);
|
||||
if (behaviourCount != ChildNetworkBehaviours.Count)
|
||||
{
|
||||
Debug.LogError($"Network Behavior Count Mismatch! [{readerPosition}][{reader.Position}]");
|
||||
Debug.LogError($"[{name}] Network Behavior Count Mismatch! [In: {behaviourCount} vs Local: {ChildNetworkBehaviours.Count}][StartReaderPos: {readerPosition}] CurrentReaderPos: {reader.Position}]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user