Compare commits
2 Commits
2.0.0-pre.
...
2.0.0-pre.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eab996f3ac | ||
|
|
a813ba0dd6 |
46
CHANGELOG.md
46
CHANGELOG.md
@@ -6,6 +6,52 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|||||||
|
|
||||||
Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).
|
Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).
|
||||||
|
|
||||||
|
## [2.0.0-pre.4] - 2024-08-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3004)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed issue where nested `NetworkTransform` components were not getting updated. (#3016)
|
||||||
|
- Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3012)
|
||||||
|
- Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#3009)
|
||||||
|
- Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#3008)
|
||||||
|
- Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3004)
|
||||||
|
- Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3004)
|
||||||
|
- Fixed issue where `NotAuthorityTarget` would include the service observer in the list of targets to send the RPC to as opposed to excluding the service observer as it should. (#3000)
|
||||||
|
- Fixed issue where `ProxyRpcTargetGroup` could attempt to send a message if there were no targets to send to. (#3000)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Changed `NetworkAnimator` to automatically switch to owner authoritative mode when using a distributed authority network topology. (#3021)
|
||||||
|
- Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004)
|
||||||
|
- Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004)
|
||||||
|
|
||||||
|
|
||||||
|
## [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)
|
||||||
|
|
||||||
|
|
||||||
## [2.0.0-pre.2] - 2024-06-17
|
## [2.0.0-pre.2] - 2024-06-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -360,6 +360,10 @@ namespace Unity.Netcode.Components
|
|||||||
|
|
||||||
public override void OnNetworkSpawn()
|
public override void OnNetworkSpawn()
|
||||||
{
|
{
|
||||||
|
if (NetworkManager.DistributedAuthorityMode)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"This component is not currently supported in distributed authority.");
|
||||||
|
}
|
||||||
base.OnNetworkSpawn();
|
base.OnNetworkSpawn();
|
||||||
m_OutstandingAuthorityChange = true;
|
m_OutstandingAuthorityChange = true;
|
||||||
ApplyAuthoritativeState();
|
ApplyAuthoritativeState();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Unity.Netcode.Components
|
|||||||
/// Half float precision <see cref="Vector3"/>.
|
/// Half float precision <see cref="Vector3"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The Vector3T<ushort> values are half float values returned by <see cref="Mathf.FloatToHalf(float)"/> for each
|
/// The Vector3T<ushort> values are half float values returned by <see cref="Mathf.FloatToHalf(float)"/> for each
|
||||||
/// individual axis and the 16 bits of the half float are stored as <see cref="ushort"/> values since C# does not have
|
/// individual axis and the 16 bits of the half float are stored as <see cref="ushort"/> values since C# does not have
|
||||||
/// a half float type.
|
/// a half float type.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Unity.Netcode.Components
|
|||||||
/// Half Precision <see cref="Vector4"/> that can also be used to convert a <see cref="Quaternion"/> to half precision.
|
/// Half Precision <see cref="Vector4"/> that can also be used to convert a <see cref="Quaternion"/> to half precision.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The Vector4T<ushort> values are half float values returned by <see cref="Mathf.FloatToHalf(float)"/> for each
|
/// The Vector4T<ushort> values are half float values returned by <see cref="Mathf.FloatToHalf(float)"/> for each
|
||||||
/// individual axis and the 16 bits of the half float are stored as <see cref="ushort"/> values since C# does not have
|
/// individual axis and the 16 bits of the half float are stored as <see cref="ushort"/> values since C# does not have
|
||||||
/// a half float type.
|
/// a half float type.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using UnityEngine;
|
|||||||
namespace Unity.Netcode
|
namespace Unity.Netcode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Solves for incoming values that are jittered
|
/// Solves for incoming values that are jittered.
|
||||||
/// Partially solves for message loss. Unclamped lerping helps hide this, but not completely
|
/// Partially solves for message loss. Unclamped lerping helps hide this, but not completely
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of interpolated value</typeparam>
|
/// <typeparam name="T">The type of interpolated value</typeparam>
|
||||||
|
|||||||
@@ -498,9 +498,13 @@ namespace Unity.Netcode.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Override this method and return false to switch to owner authoritative mode
|
/// Override this method and return false to switch to owner authoritative mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When using a distributed authority network topology, this will default to
|
||||||
|
/// owner authoritative.
|
||||||
|
/// </remarks>
|
||||||
protected virtual bool OnIsServerAuthoritative()
|
protected virtual bool OnIsServerAuthoritative()
|
||||||
{
|
{
|
||||||
return true;
|
return NetworkManager ? !NetworkManager.DistributedAuthorityMode : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animators only support up to 32 parameters
|
// Animators only support up to 32 parameters
|
||||||
@@ -851,7 +855,12 @@ namespace Unity.Netcode.Components
|
|||||||
stateChangeDetected = true;
|
stateChangeDetected = true;
|
||||||
//Debug.Log($"[Cross-Fade] To-Hash: {nt.fullPathHash} | TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) | SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
//Debug.Log($"[Cross-Fade] To-Hash: {nt.fullPathHash} | TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) | SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
||||||
}
|
}
|
||||||
else if (!tt.anyState && tt.fullPathHash != m_TransitionHash[layer])
|
// If we are not transitioned into the "any state" and the animator transition isn't a full path hash (layer to layer) and our pre-built destination state to transition does not contain the
|
||||||
|
// current layer (i.e. transitioning into a state from another layer) =or= we do contain the layer and the layer contains state to transition to is contained within our pre-built destination
|
||||||
|
// state then we can handle this transition as a non-cross fade state transition between layers.
|
||||||
|
// Otherwise, if we don't enter into this then this is a "trigger transition to some state that is now being transitioned back to the Idle state via trigger" or "Dual Triggers" IDLE<-->State.
|
||||||
|
else if (!tt.anyState && tt.fullPathHash != m_TransitionHash[layer] && (!m_DestinationStateToTransitioninfo.ContainsKey(layer) ||
|
||||||
|
(m_DestinationStateToTransitioninfo.ContainsKey(layer) && m_DestinationStateToTransitioninfo[layer].ContainsKey(nt.fullPathHash))))
|
||||||
{
|
{
|
||||||
// first time in this transition for this layer
|
// first time in this transition for this layer
|
||||||
m_TransitionHash[layer] = tt.fullPathHash;
|
m_TransitionHash[layer] = tt.fullPathHash;
|
||||||
@@ -860,6 +869,10 @@ namespace Unity.Netcode.Components
|
|||||||
animState.CrossFade = false;
|
animState.CrossFade = false;
|
||||||
animState.Transition = true;
|
animState.Transition = true;
|
||||||
animState.NormalizedTime = tt.normalizedTime;
|
animState.NormalizedTime = tt.normalizedTime;
|
||||||
|
if (m_DestinationStateToTransitioninfo.ContainsKey(layer) && m_DestinationStateToTransitioninfo[layer].ContainsKey(nt.fullPathHash))
|
||||||
|
{
|
||||||
|
animState.DestinationStateHash = nt.fullPathHash;
|
||||||
|
}
|
||||||
stateChangeDetected = true;
|
stateChangeDetected = true;
|
||||||
//Debug.Log($"[Transition] TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) |SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
//Debug.Log($"[Transition] TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) |SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,11 @@ namespace Unity.Netcode.Components
|
|||||||
{
|
{
|
||||||
if (m_IsRigidbody2D)
|
if (m_IsRigidbody2D)
|
||||||
{
|
{
|
||||||
|
#if COM_UNITY_MODULES_PHYSICS2D_LINEAR
|
||||||
|
m_Rigidbody2D.linearVelocity = linearVelocity;
|
||||||
|
#else
|
||||||
m_Rigidbody2D.velocity = linearVelocity;
|
m_Rigidbody2D.velocity = linearVelocity;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -197,7 +201,11 @@ namespace Unity.Netcode.Components
|
|||||||
{
|
{
|
||||||
if (m_IsRigidbody2D)
|
if (m_IsRigidbody2D)
|
||||||
{
|
{
|
||||||
|
#if COM_UNITY_MODULES_PHYSICS2D_LINEAR
|
||||||
|
return m_Rigidbody2D.linearVelocity;
|
||||||
|
#else
|
||||||
return m_Rigidbody2D.velocity;
|
return m_Rigidbody2D.velocity;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -238,7 +246,7 @@ namespace Unity.Netcode.Components
|
|||||||
{
|
{
|
||||||
if (m_IsRigidbody2D)
|
if (m_IsRigidbody2D)
|
||||||
{
|
{
|
||||||
return Vector3.forward * m_Rigidbody2D.velocity;
|
return Vector3.forward * m_Rigidbody2D.angularVelocity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -481,7 +489,7 @@ namespace Unity.Netcode.Components
|
|||||||
{
|
{
|
||||||
if (m_IsRigidbody2D)
|
if (m_IsRigidbody2D)
|
||||||
{
|
{
|
||||||
return m_Rigidbody2D.isKinematic;
|
return m_Rigidbody2D.bodyType == RigidbodyType2D.Kinematic;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -510,7 +518,7 @@ namespace Unity.Netcode.Components
|
|||||||
{
|
{
|
||||||
if (m_IsRigidbody2D)
|
if (m_IsRigidbody2D)
|
||||||
{
|
{
|
||||||
m_Rigidbody2D.isKinematic = isKinematic;
|
m_Rigidbody2D.bodyType = isKinematic ? RigidbodyType2D.Kinematic : RigidbodyType2D.Dynamic;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -715,7 +723,11 @@ namespace Unity.Netcode.Components
|
|||||||
|
|
||||||
if (zeroVelocity)
|
if (zeroVelocity)
|
||||||
{
|
{
|
||||||
|
#if COM_UNITY_MODULES_PHYSICS2D_LINEAR
|
||||||
|
m_Rigidbody2D.linearVelocity = Vector2.zero;
|
||||||
|
#else
|
||||||
m_Rigidbody2D.velocity = Vector2.zero;
|
m_Rigidbody2D.velocity = Vector2.zero;
|
||||||
|
#endif
|
||||||
m_Rigidbody2D.angularVelocity = 0.0f;
|
m_Rigidbody2D.angularVelocity = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2960,7 +2960,10 @@ namespace Unity.Netcode.Components
|
|||||||
#else
|
#else
|
||||||
var forUpdate = true;
|
var forUpdate = true;
|
||||||
#endif
|
#endif
|
||||||
NetworkManager?.NetworkTransformRegistration(this, forUpdate, false);
|
if (m_CachedNetworkObject != null)
|
||||||
|
{
|
||||||
|
NetworkManager?.NetworkTransformRegistration(m_CachedNetworkObject, forUpdate, false);
|
||||||
|
}
|
||||||
DeregisterForTickUpdate(this);
|
DeregisterForTickUpdate(this);
|
||||||
CanCommitToTransform = false;
|
CanCommitToTransform = false;
|
||||||
}
|
}
|
||||||
@@ -3069,7 +3072,7 @@ namespace Unity.Netcode.Components
|
|||||||
if (CanCommitToTransform)
|
if (CanCommitToTransform)
|
||||||
{
|
{
|
||||||
// Make sure authority doesn't get added to updates (no need to do this on the authority side)
|
// Make sure authority doesn't get added to updates (no need to do this on the authority side)
|
||||||
m_CachedNetworkManager.NetworkTransformRegistration(this, forUpdate, false);
|
m_CachedNetworkManager.NetworkTransformRegistration(NetworkObject, forUpdate, false);
|
||||||
if (UseHalfFloatPrecision)
|
if (UseHalfFloatPrecision)
|
||||||
{
|
{
|
||||||
m_HalfPositionState = new NetworkDeltaPosition(currentPosition, m_CachedNetworkManager.ServerTime.Tick, math.bool3(SyncPositionX, SyncPositionY, SyncPositionZ));
|
m_HalfPositionState = new NetworkDeltaPosition(currentPosition, m_CachedNetworkManager.ServerTime.Tick, math.bool3(SyncPositionX, SyncPositionY, SyncPositionZ));
|
||||||
@@ -3090,7 +3093,7 @@ namespace Unity.Netcode.Components
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Non-authority needs to be added to updates for interpolation and applying state purposes
|
// Non-authority needs to be added to updates for interpolation and applying state purposes
|
||||||
m_CachedNetworkManager.NetworkTransformRegistration(this, forUpdate, true);
|
m_CachedNetworkManager.NetworkTransformRegistration(NetworkObject, forUpdate, true);
|
||||||
// Remove this instance from the tick update
|
// Remove this instance from the tick update
|
||||||
DeregisterForTickUpdate(this);
|
DeregisterForTickUpdate(this);
|
||||||
ResetInterpolatedStateToCurrentAuthoritativeState();
|
ResetInterpolatedStateToCurrentAuthoritativeState();
|
||||||
@@ -3535,7 +3538,7 @@ namespace Unity.Netcode.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateTransformState()
|
private void UpdateTransformState()
|
||||||
{
|
{
|
||||||
if (m_CachedNetworkManager.ShutdownInProgress || (m_CachedNetworkManager.DistributedAuthorityMode && m_CachedNetworkObject.Observers.Count - 1 == 0))
|
if (m_CachedNetworkManager.ShutdownInProgress || (m_CachedNetworkManager.DistributedAuthorityMode && !m_CachedNetworkManager.CMBServiceConnection && m_CachedNetworkObject.Observers.Count - 1 == 0))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,9 +159,21 @@ namespace Unity.Netcode
|
|||||||
public bool AutoSpawnPlayerPrefabClientSide = true;
|
public bool AutoSpawnPlayerPrefabClientSide = true;
|
||||||
|
|
||||||
#if MULTIPLAYER_TOOLS
|
#if MULTIPLAYER_TOOLS
|
||||||
|
/// <summary>
|
||||||
|
/// Controls whether network messaging metrics will be gathered. (defaults to true)
|
||||||
|
/// There is a slight performance cost to having this enabled, and can increase in processing time based on network message traffic.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The Realtime Network Stats Monitoring tool requires this to be enabled.
|
||||||
|
/// </remarks>
|
||||||
|
[Tooltip("Enable (default) if you want to gather messaging metrics. Realtime Network Stats Monitor requires this to be enabled. Disabling this can improve performance in release builds.")]
|
||||||
public bool NetworkMessageMetrics = true;
|
public bool NetworkMessageMetrics = true;
|
||||||
#endif
|
#endif
|
||||||
|
/// <summary>
|
||||||
|
/// When enabled (default, this enables network profiling information. This does come with a per message processing cost.
|
||||||
|
/// Network profiling information is automatically disabled in release builds.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("Enable (default) if you want to profile network messages with development builds and defaults to being disabled in release builds. When disabled, network messaging profiling will be disabled in development builds.")]
|
||||||
public bool NetworkProfilingMetrics = true;
|
public bool NetworkProfilingMetrics = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base class to override to write network code. Inherits MonoBehaviour
|
/// The base class to override to write network code. Inherits MonoBehaviour.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class NetworkBehaviour : MonoBehaviour
|
public abstract class NetworkBehaviour : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ namespace Unity.Netcode
|
|||||||
// RuntimeAccessModifiersILPP will make this `public`
|
// RuntimeAccessModifiersILPP will make this `public`
|
||||||
internal static readonly Dictionary<Type, Dictionary<uint, RpcReceiveHandler>> __rpc_func_table = new Dictionary<Type, Dictionary<uint, RpcReceiveHandler>>();
|
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`
|
// RuntimeAccessModifiersILPP will make this `public`
|
||||||
internal static readonly Dictionary<Type, Dictionary<uint, string>> __rpc_name_table = new Dictionary<Type, Dictionary<uint, string>>();
|
internal static readonly Dictionary<Type, Dictionary<uint, string>> __rpc_name_table = new Dictionary<Type, Dictionary<uint, string>>();
|
||||||
#endif
|
#endif
|
||||||
@@ -124,7 +124,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
bufferWriter.Dispose();
|
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 (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
NetworkManager.NetworkMetrics.TrackRpcSent(
|
NetworkManager.NetworkMetrics.TrackRpcSent(
|
||||||
@@ -252,7 +252,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
bufferWriter.Dispose();
|
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 (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
if (clientRpcParams.Send.TargetClientIds != null)
|
if (clientRpcParams.Send.TargetClientIds != null)
|
||||||
@@ -410,8 +410,8 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the NetworkManager that owns this NetworkBehaviour instance
|
/// 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
|
/// See `NetworkObject` note for how there is a chicken/egg problem when not initialized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NetworkManager NetworkManager
|
public NetworkManager NetworkManager
|
||||||
{
|
{
|
||||||
@@ -439,38 +439,40 @@ namespace Unity.Netcode
|
|||||||
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeArray{ulong})"/>,
|
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeArray{ulong})"/>,
|
||||||
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeList{ulong})"/>,
|
/// <see cref="Unity.Netcode.RpcTarget.Not(NativeList{ulong})"/>,
|
||||||
/// <see cref="Unity.Netcode.RpcTarget.Not(ulong[])"/>, and
|
/// <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>
|
/// </summary>
|
||||||
#pragma warning restore IDE0001
|
#pragma warning restore IDE0001
|
||||||
public RpcTarget RpcTarget => NetworkManager.RpcTarget;
|
public RpcTarget RpcTarget => NetworkManager.RpcTarget;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If a NetworkObject is assigned, it will return whether or not this NetworkObject
|
/// If a NetworkObject is assigned, returns whether the NetworkObject
|
||||||
/// is the local player object. If no NetworkObject is assigned it will always return false.
|
/// is the local player object. If no NetworkObject is assigned, returns false.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsLocalPlayer { get; private set; }
|
public bool IsLocalPlayer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public bool IsOwner { get; internal set; }
|
public bool IsOwner { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if we are executing as server
|
/// Gets whether executing as a server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsServer { get; private set; }
|
public bool IsServer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the local client has authority over the associated NetworkObject
|
/// Determines if the local client has authority over the associated NetworkObject.
|
||||||
/// Client-Server: This will return true if IsServer or IsHost
|
/// <list type="bullet">
|
||||||
/// Distributed Authority: This will return true if IsOwner
|
/// <item>In client-server contexts: returns true if `IsServer` or `IsHost`.</item>
|
||||||
|
/// <item>In distributed authority contexts: returns true if `IsOwner`.</item>
|
||||||
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasAuthority { get; internal set; }
|
public bool HasAuthority { get; internal set; }
|
||||||
|
|
||||||
internal NetworkClient LocalClient { get; private set; }
|
internal NetworkClient LocalClient { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if the client is the distributed authority mode session owner
|
/// Gets whether the client is the distributed authority mode session owner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSessionOwner
|
public bool IsSessionOwner
|
||||||
{
|
{
|
||||||
@@ -486,29 +488,29 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public bool ServerIsHost { get; private set; }
|
public bool ServerIsHost { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if we are executing as client
|
/// Gets whether executing as a client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsClient { get; private set; }
|
public bool IsClient { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if we are executing as Host, I.E Server and Client
|
/// Gets whether executing as a host (both server and client).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsHost { get; private set; }
|
public bool IsHost { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets Whether or not the object has a owner
|
/// Gets whether the object has an owner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsOwnedByServer { get; internal set; }
|
public bool IsOwnedByServer { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to determine if it is safe to access NetworkObject and NetworkManager from within a NetworkBehaviour component
|
/// Determines whether it's safe to access a NetworkObject and NetworkManager from within a NetworkBehaviour component.
|
||||||
/// Primarily useful when checking NetworkObject/NetworkManager properties within FixedUpate
|
/// Primarily useful when checking NetworkObject or NetworkManager properties within FixedUpate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSpawned { get; internal set; }
|
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
|
/// 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
|
/// how NetworkObject works but it was close to the release and too risky to change
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the NetworkObject that owns this NetworkBehaviour instance
|
/// Gets the NetworkObject that owns this NetworkBehaviour instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NetworkObject NetworkObject
|
public NetworkObject NetworkObject
|
||||||
{
|
{
|
||||||
@@ -567,19 +569,19 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether or not this NetworkBehaviour instance has a NetworkObject owner.
|
/// Gets whether this NetworkBehaviour instance has a NetworkObject owner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasNetworkObject => NetworkObject != null;
|
public bool HasNetworkObject => NetworkObject != null;
|
||||||
|
|
||||||
private NetworkObject m_NetworkObject = null;
|
private NetworkObject m_NetworkObject = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the NetworkId of the NetworkObject that owns this NetworkBehaviour
|
/// Gets the NetworkId of the NetworkObject that owns this NetworkBehaviour instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong NetworkObjectId { get; internal set; }
|
public ulong NetworkObjectId { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets NetworkId for this NetworkBehaviour from the owner NetworkObject
|
/// Gets NetworkId for this NetworkBehaviour from the owner NetworkObject.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort NetworkBehaviourId { get; internal set; }
|
public ushort NetworkBehaviourId { get; internal set; }
|
||||||
|
|
||||||
@@ -589,7 +591,7 @@ namespace Unity.Netcode
|
|||||||
internal ushort NetworkBehaviourIdCache = 0;
|
internal ushort NetworkBehaviourIdCache = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="behaviourId">The behaviourId to return</param>
|
/// <param name="behaviourId">The behaviourId to return</param>
|
||||||
/// <returns>Returns NetworkBehaviour with given behaviourId</returns>
|
/// <returns>Returns NetworkBehaviour with given behaviourId</returns>
|
||||||
@@ -599,7 +601,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the ClientId that owns the NetworkObject
|
/// Gets the ClientId that owns this NetworkObject.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong OwnerClientId { get; internal set; }
|
public ulong OwnerClientId { get; internal set; }
|
||||||
|
|
||||||
@@ -651,28 +653,29 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Invoked only on the authority instance when a <see cref="NetworkObject"/> is deferring its despawn on non-authoritative instances.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// See also: <see cref="NetworkObject.DeferDespawn(int, bool)"/>
|
/// See also: <see cref="NetworkObject.DeferDespawn(int, bool)"/>
|
||||||
/// </remarks>
|
/// </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) { }
|
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.
|
/// 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>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// <param name="networkManager">a ref to the <see cref="NetworkManager"/> since this is not yet set on the <see cref="NetworkBehaviour"/></param>
|
/// <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.
|
/// 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.
|
/// 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.
|
/// This can be used to handle things like initializing a NetworkVariable.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected virtual void OnNetworkPreSpawn(ref NetworkManager networkManager) { }
|
protected virtual void OnNetworkPreSpawn(ref NetworkManager networkManager) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public virtual void OnNetworkSpawn() { }
|
public virtual void OnNetworkSpawn() { }
|
||||||
|
|
||||||
@@ -686,28 +689,28 @@ namespace Unity.Netcode
|
|||||||
protected virtual void OnNetworkPostSpawn() { }
|
protected virtual void OnNetworkPostSpawn() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Client-Side Only]
|
/// This method is only available client-side.
|
||||||
/// 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
|
/// 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
|
/// <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.
|
/// will have this method invoked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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.
|
/// This is only invoked on clients during a client-server network topology session.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected virtual void OnNetworkSessionSynchronized() { }
|
protected virtual void OnNetworkSessionSynchronized() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Client & Server Side]
|
/// 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.
|
||||||
/// 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.
|
/// This method runs both client and server side.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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>
|
/// </remarks>
|
||||||
protected virtual void OnInSceneObjectsSpawned() { }
|
protected virtual void OnInSceneObjectsSpawned() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public virtual void OnNetworkDespawn() { }
|
public virtual void OnNetworkDespawn() { }
|
||||||
|
|
||||||
@@ -803,7 +806,8 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets called when the local client gains ownership of this object
|
/// In client-server contexts, this method is invoked on both the server and the local client of the owner when <see cref="Netcode.NetworkObject"/> ownership is assigned.
|
||||||
|
/// <para>In distributed authority contexts, this method is only invoked on the local client that has been assigned ownership of the associated <see cref="Netcode.NetworkObject"/>.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnGainedOwnership() { }
|
public virtual void OnGainedOwnership() { }
|
||||||
|
|
||||||
@@ -814,8 +818,8 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked on all clients, override this method to be notified of any
|
/// Invoked on all clients. Override this method to be notified of any
|
||||||
/// ownership changes (even if the instance was niether the previous or
|
/// ownership changes (even if the instance was neither the previous or
|
||||||
/// newly assigned current owner).
|
/// newly assigned current owner).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="previous">the previous owner</param>
|
/// <param name="previous">the previous owner</param>
|
||||||
@@ -831,7 +835,9 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets called when we loose ownership of this object
|
/// In client-server contexts, this method is invoked on the local client when it loses ownership of the associated <see cref="Netcode.NetworkObject"/>
|
||||||
|
/// and on the server when any client loses ownership.
|
||||||
|
/// <para>In distributed authority contexts, this method is only invoked on the local client that has lost ownership of the associated <see cref="Netcode.NetworkObject"/>.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnLostOwnership() { }
|
public virtual void OnLostOwnership() { }
|
||||||
|
|
||||||
@@ -842,7 +848,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="parentNetworkObject">the new <see cref="NetworkObject"/> parent</param>
|
/// <param name="parentNetworkObject">the new <see cref="NetworkObject"/> parent</param>
|
||||||
public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { }
|
public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { }
|
||||||
@@ -877,7 +883,7 @@ namespace Unity.Netcode
|
|||||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||||
{
|
{
|
||||||
__rpc_func_table[GetType()][hash] = handler;
|
__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;
|
__rpc_name_table[GetType()][hash] = rpcMethodName;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -903,7 +909,7 @@ namespace Unity.Netcode
|
|||||||
if (!__rpc_func_table.ContainsKey(GetType()))
|
if (!__rpc_func_table.ContainsKey(GetType()))
|
||||||
{
|
{
|
||||||
__rpc_func_table[GetType()] = new Dictionary<uint, RpcReceiveHandler>();
|
__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>();
|
__rpc_name_table[GetType()] = new Dictionary<uint, string>();
|
||||||
#endif
|
#endif
|
||||||
__initializeRpcs();
|
__initializeRpcs();
|
||||||
@@ -1112,31 +1118,38 @@ namespace Unity.Netcode
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClientId)
|
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;
|
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);
|
writer.WriteValueSafe((ushort)NetworkVariableFields.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exit early if there are no NetworkVariables
|
||||||
if (NetworkVariableFields.Count == 0)
|
if (NetworkVariableFields.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
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++)
|
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 (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;
|
var writePos = writer.Position;
|
||||||
// Note: This value can't be packed because we don't know how large it will be in advance
|
// 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
|
// we reserve space for it, then write the data, then come back and fill in the space
|
||||||
@@ -1148,18 +1161,19 @@ namespace Unity.Netcode
|
|||||||
NetworkVariableFields[j].WriteField(writer);
|
NetworkVariableFields[j].WriteField(writer);
|
||||||
var size = writer.Position - startPos;
|
var size = writer.Position - startPos;
|
||||||
writer.Seek(writePos);
|
writer.Seek(writePos);
|
||||||
|
// Write the NetworkVariable value
|
||||||
writer.WriteValueSafe((ushort)size);
|
writer.WriteValueSafe((ushort)size);
|
||||||
writer.Seek(startPos + 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);
|
NetworkVariableFields[j].WriteField(writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (ensureLengthSafety)
|
||||||
{
|
{
|
||||||
// Only if EnsureNetworkVariableLengthSafety, otherwise just skip
|
// Client-Server Only: If the client cannot read this field, then skip it but write a 0 for this NetworkVariable's position
|
||||||
if (networkManager.DistributedAuthorityMode || networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe((ushort)0);
|
writer.WriteValueSafe((ushort)0);
|
||||||
}
|
}
|
||||||
@@ -1177,75 +1191,78 @@ namespace Unity.Netcode
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId)
|
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;
|
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);
|
reader.ReadValueSafe(out ushort variableCount);
|
||||||
if (variableCount != NetworkVariableFields.Count)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exit early if nothing else to read
|
||||||
if (NetworkVariableFields.Count == 0)
|
if (NetworkVariableFields.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
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++)
|
for (int j = 0; j < NetworkVariableFields.Count; j++)
|
||||||
{
|
{
|
||||||
var varSize = (ushort)0;
|
var varSize = (ushort)0;
|
||||||
var readStartPos = 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 (ensureLengthSafety || distributedAuthority)
|
||||||
if (varSize == 0)
|
|
||||||
{
|
{
|
||||||
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
|
else // Client-Server Only: If the client cannot read this field, then skip it
|
||||||
if (!NetworkVariableFields[j].CanClientRead(clientId))
|
|
||||||
{
|
{
|
||||||
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);
|
reader.ReadValueSafe(out ushort size);
|
||||||
if (size != 0)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkManager.DistributedAuthorityMode)
|
// Read the NetworkVarible value
|
||||||
{
|
NetworkVariableFields[j].ReadField(reader);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
// When EnsureNetworkVariableLengthSafety or DistributedAuthorityMode always do a bounds check
|
||||||
|
if (ensureLengthSafety || distributedAuthority)
|
||||||
{
|
{
|
||||||
if (reader.Position > (readStartPos + varSize))
|
if (reader.Position > (readStartPos + varSize))
|
||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
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);
|
reader.Seek(readStartPos + varSize);
|
||||||
@@ -1254,7 +1271,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
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);
|
reader.Seek(readStartPos + varSize);
|
||||||
@@ -1264,7 +1281,7 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local instance of a object with a given NetworkId
|
/// Gets the local instance of a NetworkObject with a given NetworkId.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="networkId"></param>
|
/// <param name="networkId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -1275,14 +1292,14 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Override this method if your derived NetworkBehaviour requires custom synchronization data.
|
/// 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
|
/// and will increase the payload size for client synchronization and dynamically spawned
|
||||||
/// <see cref="NetworkObject"/>s.
|
/// <see cref="NetworkObject"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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 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.
|
/// NetworkObject being spawned.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="serializer">The serializer to use to read and write the data.</param>
|
/// <param name="serializer">The serializer to use to read and write the data.</param>
|
||||||
@@ -1305,10 +1322,10 @@ namespace Unity.Netcode
|
|||||||
/// The relative client identifier targeted for the serialization of this <see cref="NetworkBehaviour"/> instance.
|
/// The relative client identifier targeted for the serialization of this <see cref="NetworkBehaviour"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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 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"/>.
|
/// 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>
|
/// </remarks>
|
||||||
protected ulong m_TargetIdBeingSynchronized { get; private set; }
|
protected ulong m_TargetIdBeingSynchronized { get; private set; }
|
||||||
|
|
||||||
@@ -1431,9 +1448,8 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the <see cref="GameObject"/> the <see cref="NetworkBehaviour"/> is attached to.
|
/// Invoked when the <see cref="GameObject"/> the <see cref="NetworkBehaviour"/> is attached to is destroyed.
|
||||||
/// NOTE: If you override this, you will want to always invoke this base class version of this
|
/// If you override this, you must always invoke the base class version of this <see cref="OnDestroy"/> method.
|
||||||
/// <see cref="OnDestroy"/> method!!
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnDestroy()
|
public virtual void OnDestroy()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using UnityEditor;
|
|||||||
#endif
|
#endif
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using Debug = UnityEngine.Debug;
|
using Debug = UnityEngine.Debug;
|
||||||
using Unity.Netcode.Components;
|
|
||||||
|
|
||||||
namespace Unity.Netcode
|
namespace Unity.Netcode
|
||||||
{
|
{
|
||||||
@@ -29,13 +28,40 @@ namespace Unity.Netcode
|
|||||||
// RuntimeAccessModifiersILPP will make this `public`
|
// RuntimeAccessModifiersILPP will make this `public`
|
||||||
internal static readonly Dictionary<uint, RpcReceiveHandler> __rpc_func_table = new Dictionary<uint, RpcReceiveHandler>();
|
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`
|
// RuntimeAccessModifiersILPP will make this `public`
|
||||||
internal static readonly Dictionary<uint, string> __rpc_name_table = new Dictionary<uint, string>();
|
internal static readonly Dictionary<uint, string> __rpc_name_table = new Dictionary<uint, string>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
#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;
|
internal static bool IsDistributedAuthority;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -188,25 +214,25 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Dictionary<ulong, NetworkTransform> NetworkTransformUpdate = new Dictionary<ulong, NetworkTransform>();
|
internal Dictionary<ulong, NetworkObject> NetworkTransformUpdate = new Dictionary<ulong, NetworkObject>();
|
||||||
#if COM_UNITY_MODULES_PHYSICS
|
#if COM_UNITY_MODULES_PHYSICS
|
||||||
internal Dictionary<ulong, NetworkTransform> NetworkTransformFixedUpdate = new Dictionary<ulong, NetworkTransform>();
|
internal Dictionary<ulong, NetworkObject> NetworkTransformFixedUpdate = new Dictionary<ulong, NetworkObject>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
internal void NetworkTransformRegistration(NetworkTransform networkTransform, bool forUpdate = true, bool register = true)
|
internal void NetworkTransformRegistration(NetworkObject networkObject, bool onUpdate = true, bool register = true)
|
||||||
{
|
{
|
||||||
if (forUpdate)
|
if (onUpdate)
|
||||||
{
|
{
|
||||||
if (register)
|
if (register)
|
||||||
{
|
{
|
||||||
if (!NetworkTransformUpdate.ContainsKey(networkTransform.NetworkObjectId))
|
if (!NetworkTransformUpdate.ContainsKey(networkObject.NetworkObjectId))
|
||||||
{
|
{
|
||||||
NetworkTransformUpdate.Add(networkTransform.NetworkObjectId, networkTransform);
|
NetworkTransformUpdate.Add(networkObject.NetworkObjectId, networkObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NetworkTransformUpdate.Remove(networkTransform.NetworkObjectId);
|
NetworkTransformUpdate.Remove(networkObject.NetworkObjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if COM_UNITY_MODULES_PHYSICS
|
#if COM_UNITY_MODULES_PHYSICS
|
||||||
@@ -214,14 +240,14 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
if (register)
|
if (register)
|
||||||
{
|
{
|
||||||
if (!NetworkTransformFixedUpdate.ContainsKey(networkTransform.NetworkObjectId))
|
if (!NetworkTransformFixedUpdate.ContainsKey(networkObject.NetworkObjectId))
|
||||||
{
|
{
|
||||||
NetworkTransformFixedUpdate.Add(networkTransform.NetworkObjectId, networkTransform);
|
NetworkTransformFixedUpdate.Add(networkObject.NetworkObjectId, networkObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NetworkTransformFixedUpdate.Remove(networkTransform.NetworkObjectId);
|
NetworkTransformFixedUpdate.Remove(networkObject.NetworkObjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -262,11 +288,21 @@ namespace Unity.Netcode
|
|||||||
#if COM_UNITY_MODULES_PHYSICS
|
#if COM_UNITY_MODULES_PHYSICS
|
||||||
case NetworkUpdateStage.FixedUpdate:
|
case NetworkUpdateStage.FixedUpdate:
|
||||||
{
|
{
|
||||||
foreach (var networkTransformEntry in NetworkTransformFixedUpdate)
|
foreach (var networkObjectEntry in NetworkTransformFixedUpdate)
|
||||||
{
|
{
|
||||||
if (networkTransformEntry.Value.gameObject.activeInHierarchy && networkTransformEntry.Value.IsSpawned)
|
// if not active or not spawned then skip
|
||||||
|
if (!networkObjectEntry.Value.gameObject.activeInHierarchy || !networkObjectEntry.Value.IsSpawned)
|
||||||
{
|
{
|
||||||
networkTransformEntry.Value.OnFixedUpdate();
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var networkTransformEntry in networkObjectEntry.Value.NetworkTransforms)
|
||||||
|
{
|
||||||
|
// only update if enabled
|
||||||
|
if (networkTransformEntry.enabled)
|
||||||
|
{
|
||||||
|
networkTransformEntry.OnFixedUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,11 +317,21 @@ namespace Unity.Netcode
|
|||||||
case NetworkUpdateStage.PreLateUpdate:
|
case NetworkUpdateStage.PreLateUpdate:
|
||||||
{
|
{
|
||||||
// Non-physics based non-authority NetworkTransforms update their states after all other components
|
// Non-physics based non-authority NetworkTransforms update their states after all other components
|
||||||
foreach (var networkTransformEntry in NetworkTransformUpdate)
|
foreach (var networkObjectEntry in NetworkTransformUpdate)
|
||||||
{
|
{
|
||||||
if (networkTransformEntry.Value.gameObject.activeInHierarchy && networkTransformEntry.Value.IsSpawned)
|
// if not active or not spawned then skip
|
||||||
|
if (!networkObjectEntry.Value.gameObject.activeInHierarchy || !networkObjectEntry.Value.IsSpawned)
|
||||||
{
|
{
|
||||||
networkTransformEntry.Value.OnUpdate();
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var networkTransformEntry in networkObjectEntry.Value.NetworkTransforms)
|
||||||
|
{
|
||||||
|
// only update if enabled
|
||||||
|
if (networkTransformEntry.enabled)
|
||||||
|
{
|
||||||
|
networkTransformEntry.OnUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1062,6 +1108,13 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
internal void Initialize(bool server)
|
internal void Initialize(bool server)
|
||||||
{
|
{
|
||||||
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||||
|
if (!DisableNotOptimizedSerializedType)
|
||||||
|
{
|
||||||
|
s_SerializedType.Clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if COM_UNITY_MODULES_PHYSICS
|
#if COM_UNITY_MODULES_PHYSICS
|
||||||
NetworkTransformFixedUpdate.Clear();
|
NetworkTransformFixedUpdate.Clear();
|
||||||
#endif
|
#endif
|
||||||
@@ -1250,17 +1303,8 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
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.
|
// Notify the server that everything should be synchronized/spawned at this time.
|
||||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||||
{
|
|
||||||
networkObject.InternalNetworkSessionSynchronized();
|
|
||||||
}
|
|
||||||
OnServerStarted?.Invoke();
|
OnServerStarted?.Invoke();
|
||||||
ConnectionManager.LocalClient.IsApproved = true;
|
ConnectionManager.LocalClient.IsApproved = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -1407,17 +1451,9 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
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.
|
// Notify the host that everything should be synchronized/spawned at this time.
|
||||||
foreach (var networkObject in SpawnManager.SpawnedObjectsList)
|
SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||||
{
|
|
||||||
networkObject.InternalNetworkSessionSynchronized();
|
|
||||||
}
|
|
||||||
|
|
||||||
OnServerStarted?.Invoke();
|
OnServerStarted?.Invoke();
|
||||||
OnClientStarted?.Invoke();
|
OnClientStarted?.Invoke();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Unity.Netcode
|
|||||||
internal uint PrefabGlobalObjectIdHash;
|
internal uint PrefabGlobalObjectIdHash;
|
||||||
|
|
||||||
/// <summary>
|
/// <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,
|
/// placd NetworkObjects that are not prefab instances, dynamically spawned prefab instances,
|
||||||
/// or for network prefab assets.
|
/// or for network prefab assets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -207,8 +207,8 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This checks to see if this NetworkObject is an in-scene placed prefab instance. If so it will
|
/// 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
|
/// automatically find the source prefab asset's GlobalObjectIdHash value, assign it to
|
||||||
/// InScenePlacedSourceGlobalObjectIdHash and mark this as being in-scene placed.
|
/// InScenePlacedSourceGlobalObjectIdHash and mark this as being in-scene placed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
@@ -540,8 +540,8 @@ namespace Unity.Netcode
|
|||||||
/// permission failure status codes will be returned via <see cref="OnOwnershipPermissionsFailure"/>.
|
/// 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="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="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="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.
|
/// <see cref="NotTransferrable"/>: The <see cref="NetworkObject"/> does not have the <see cref="OwnershipStatus.Transferable"/> flag set and ownership cannot be acquired.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum OwnershipPermissionsFailureStatus
|
public enum OwnershipPermissionsFailureStatus
|
||||||
{
|
{
|
||||||
@@ -1547,6 +1547,11 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
if (NetworkManager.DistributedAuthorityMode)
|
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)
|
if (NetworkManager.NetworkConfig.EnableSceneManagement)
|
||||||
{
|
{
|
||||||
NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[gameObject.scene.handle];
|
NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[gameObject.scene.handle];
|
||||||
@@ -1638,7 +1643,7 @@ namespace Unity.Netcode
|
|||||||
return null;
|
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
|
// We only need to check for authority when running in client-server mode
|
||||||
if (!networkManager.IsServer && !networkManager.DistributedAuthorityMode)
|
if (!networkManager.IsServer && !networkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
@@ -2354,7 +2359,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
m_ChildNetworkBehaviours.Add(networkBehaviours[i]);
|
m_ChildNetworkBehaviours.Add(networkBehaviours[i]);
|
||||||
var type = networkBehaviours[i].GetType();
|
var type = networkBehaviours[i].GetType();
|
||||||
if (type.IsInstanceOfType(typeof(NetworkTransform)) || type.IsSubclassOf(typeof(NetworkTransform)))
|
if (type == typeof(NetworkTransform) || type.IsInstanceOfType(typeof(NetworkTransform)) || type.IsSubclassOf(typeof(NetworkTransform)))
|
||||||
{
|
{
|
||||||
if (NetworkTransforms == null)
|
if (NetworkTransforms == null)
|
||||||
{
|
{
|
||||||
@@ -2436,10 +2441,10 @@ namespace Unity.Netcode
|
|||||||
if (NetworkManager.DistributedAuthorityMode)
|
if (NetworkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
var readerPosition = reader.Position;
|
var readerPosition = reader.Position;
|
||||||
reader.ReadValueSafe(out ushort behaviorCount);
|
reader.ReadValueSafe(out ushort behaviourCount);
|
||||||
if (behaviorCount != ChildNetworkBehaviours.Count)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Unity.Netcode
|
|||||||
public void Handle(ref NetworkContext context)
|
public void Handle(ref NetworkContext context)
|
||||||
{
|
{
|
||||||
var networkManager = (NetworkManager)context.SystemOwner;
|
var networkManager = (NetworkManager)context.SystemOwner;
|
||||||
if ((ShouldSynchronize || networkManager.CMBServiceConnection) && networkManager.DistributedAuthorityMode && networkManager.LocalClient.IsSessionOwner)
|
if (ShouldSynchronize && networkManager.NetworkConfig.EnableSceneManagement && networkManager.DistributedAuthorityMode && networkManager.LocalClient.IsSessionOwner)
|
||||||
{
|
{
|
||||||
networkManager.SceneManager.SynchronizeNetworkObjects(ClientId);
|
networkManager.SceneManager.SynchronizeNetworkObjects(ClientId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,10 +224,7 @@ namespace Unity.Netcode
|
|||||||
networkManager.ConnectionManager.InvokeOnClientConnectedCallback(context.SenderId);
|
networkManager.ConnectionManager.InvokeOnClientConnectedCallback(context.SenderId);
|
||||||
|
|
||||||
// For convenience, notify all NetworkBehaviours that synchronization is complete.
|
// For convenience, notify all NetworkBehaviours that synchronization is complete.
|
||||||
foreach (var networkObject in networkManager.SpawnManager.SpawnedObjectsList)
|
networkManager.SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||||
{
|
|
||||||
networkObject.InternalNetworkSessionSynchronized();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -240,16 +237,12 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
if (!IsRestoredSession)
|
if (!IsRestoredSession)
|
||||||
{
|
{
|
||||||
|
// Synchronize the service with the initial session owner's loaded scenes and spawned objects
|
||||||
|
networkManager.SceneManager.SynchronizeNetworkObjects(NetworkManager.ServerClientId);
|
||||||
|
|
||||||
// Spawn any in-scene placed NetworkObjects
|
// Spawn any in-scene placed NetworkObjects
|
||||||
networkManager.SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
networkManager.SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
||||||
|
|
||||||
// With scene management enabled and since the session owner doesn't send a Synchronize scene event synchronize itself,
|
|
||||||
// we need to notify the session owner that all in-scnee placed NetworkObjects are spawned at this time.
|
|
||||||
foreach (var networkObject in networkManager.SpawnManager.SpawnedObjectsList)
|
|
||||||
{
|
|
||||||
networkObject.InternalInSceneNetworkObjectsSpawned();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn the local player of the session owner
|
// Spawn the local player of the session owner
|
||||||
if (networkManager.AutoSpawnPlayerPrefabClientSide)
|
if (networkManager.AutoSpawnPlayerPrefabClientSide)
|
||||||
{
|
{
|
||||||
@@ -261,10 +254,7 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
// With scene management enabled and since the session owner doesn't send a Synchronize scene event synchronize itself,
|
// With scene management enabled and since the session owner doesn't send a Synchronize scene event synchronize itself,
|
||||||
// we need to notify the session owner that everything should be synchronized/spawned at this time.
|
// we need to notify the session owner that everything should be synchronized/spawned at this time.
|
||||||
foreach (var networkObject in networkManager.SpawnManager.SpawnedObjectsList)
|
networkManager.SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||||
{
|
|
||||||
networkObject.InternalNetworkSessionSynchronized();
|
|
||||||
}
|
|
||||||
|
|
||||||
// When scene management is enabled and since the session owner is synchronizing the service (i.e. acting like host),
|
// When scene management is enabled and since the session owner is synchronizing the service (i.e. acting like host),
|
||||||
// we need to locallyh invoke the OnClientConnected callback at this point in time.
|
// we need to locallyh invoke the OnClientConnected callback at this point in time.
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
private const string k_Name = "NetworkVariableDeltaMessage";
|
private const string k_Name = "NetworkVariableDeltaMessage";
|
||||||
|
|
||||||
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
|
|
||||||
// Worth either merging or more cleanly separating these codepaths.
|
|
||||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||||
{
|
{
|
||||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize(NetworkObjectId) + FastBufferWriter.GetWriteSize(NetworkBehaviourIndex)))
|
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize(NetworkObjectId) + FastBufferWriter.GetWriteSize(NetworkBehaviourIndex)))
|
||||||
@@ -126,10 +124,6 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// DANGO-TODO:
|
|
||||||
// Complex types with custom type serialization (either registered custom types or INetworkSerializable implementations) will be problematic
|
|
||||||
// Non-complex types always provide a full state update per delta
|
|
||||||
// DANGO-TODO: Add NetworkListEvent<T>.EventType awareness to the cloud-state server
|
|
||||||
if (networkManager.DistributedAuthorityMode)
|
if (networkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
var size_marker = writer.Position;
|
var size_marker = writer.Position;
|
||||||
@@ -167,8 +161,6 @@ namespace Unity.Netcode
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
|
|
||||||
// Worth either merging or more cleanly separating these codepaths.
|
|
||||||
public void Handle(ref NetworkContext context)
|
public void Handle(ref NetworkContext context)
|
||||||
{
|
{
|
||||||
var networkManager = (NetworkManager)context.SystemOwner;
|
var networkManager = (NetworkManager)context.SystemOwner;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
payload = new FastBufferReader(reader.GetUnsafePtrAtCurrentPosition(), Allocator.None, reader.Length - reader.Position);
|
payload = new FastBufferReader(reader.GetUnsafePtrAtCurrentPosition(), Allocator.None, reader.Length - reader.Position);
|
||||||
|
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
if (NetworkBehaviour.__rpc_name_table[networkBehaviour.GetType()].TryGetValue(metadata.NetworkRpcMethodId, out var rpcMethodName))
|
if (NetworkBehaviour.__rpc_name_table[networkBehaviour.GetType()].TryGetValue(metadata.NetworkRpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
networkManager.NetworkMetrics.TrackRpcReceived(
|
networkManager.NetworkMetrics.TrackRpcReceived(
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
private protected void SendMessageToClient(NetworkBehaviour behaviour, ulong clientId, ref RpcMessage message, NetworkDelivery delivery)
|
private protected void SendMessageToClient(NetworkBehaviour behaviour, ulong clientId, ref RpcMessage message, NetworkDelivery delivery)
|
||||||
{
|
{
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
var size =
|
var size =
|
||||||
#endif
|
#endif
|
||||||
behaviour.NetworkManager.MessageManager.SendMessage(ref message, delivery, clientId);
|
behaviour.NetworkManager.MessageManager.SendMessage(ref message, delivery, clientId);
|
||||||
|
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
behaviour.NetworkManager.NetworkMetrics.TrackRpcSent(
|
behaviour.NetworkManager.NetworkMetrics.TrackRpcSent(
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace Unity.Netcode
|
|||||||
message.Handle(ref context);
|
message.Handle(ref context);
|
||||||
length = tempBuffer.Length;
|
length = tempBuffer.Length;
|
||||||
}
|
}
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
networkManager.NetworkMetrics.TrackRpcSent(
|
networkManager.NetworkMetrics.TrackRpcSent(
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The CMB-Service holds ID 0 and should not be added to the targets
|
||||||
|
if (clientId == NetworkManager.ServerClientId && m_NetworkManager.CMBServiceConnection)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
m_GroupSendTarget.Add(clientId);
|
m_GroupSendTarget.Add(clientId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,6 +47,12 @@ namespace Unity.Netcode
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The CMB-Service holds ID 0 and should not be added to the targets
|
||||||
|
if (clientId == NetworkManager.ServerClientId && m_NetworkManager.CMBServiceConnection)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (clientId == m_NetworkManager.LocalClientId)
|
if (clientId == m_NetworkManager.LocalClientId)
|
||||||
{
|
{
|
||||||
m_LocalSendRpcTarget.Send(behaviour, ref message, delivery, rpcParams);
|
m_LocalSendRpcTarget.Send(behaviour, ref message, delivery, rpcParams);
|
||||||
|
|||||||
@@ -17,13 +17,18 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams)
|
internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams)
|
||||||
{
|
{
|
||||||
|
// If there are no targets then don't attempt to send anything.
|
||||||
|
if (TargetClientIds.Length == 0 && Ids.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
var proxyMessage = new ProxyMessage { Delivery = delivery, TargetClientIds = TargetClientIds.AsArray(), WrappedMessage = message };
|
var proxyMessage = new ProxyMessage { Delivery = delivery, TargetClientIds = TargetClientIds.AsArray(), WrappedMessage = message };
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
var size =
|
var size =
|
||||||
#endif
|
#endif
|
||||||
behaviour.NetworkManager.MessageManager.SendMessage(ref proxyMessage, delivery, NetworkManager.ServerClientId);
|
behaviour.NetworkManager.MessageManager.SendMessage(ref proxyMessage, delivery, NetworkManager.ServerClientId);
|
||||||
|
|
||||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
|
||||||
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
|
||||||
{
|
{
|
||||||
foreach (var clientId in TargetClientIds)
|
foreach (var clientId in TargetClientIds)
|
||||||
|
|||||||
@@ -94,18 +94,18 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
case NetworkListEvent<T>.EventType.Add:
|
case NetworkListEvent<T>.EventType.Add:
|
||||||
{
|
{
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref element.Value);
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref element.Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetworkListEvent<T>.EventType.Insert:
|
case NetworkListEvent<T>.EventType.Insert:
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, element.Index);
|
BytePacker.WriteValueBitPacked(writer, element.Index);
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref element.Value);
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref element.Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetworkListEvent<T>.EventType.Remove:
|
case NetworkListEvent<T>.EventType.Remove:
|
||||||
{
|
{
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref element.Value);
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref element.Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetworkListEvent<T>.EventType.RemoveAt:
|
case NetworkListEvent<T>.EventType.RemoveAt:
|
||||||
@@ -116,7 +116,7 @@ namespace Unity.Netcode
|
|||||||
case NetworkListEvent<T>.EventType.Value:
|
case NetworkListEvent<T>.EventType.Value:
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, element.Index);
|
BytePacker.WriteValueBitPacked(writer, element.Index);
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref element.Value);
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref element.Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetworkListEvent<T>.EventType.Clear:
|
case NetworkListEvent<T>.EventType.Clear:
|
||||||
@@ -133,13 +133,13 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
if (m_NetworkManager.DistributedAuthorityMode)
|
if (m_NetworkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe(NetworkVariableSerialization<T>.Type);
|
writer.WriteValueSafe(NetworkVariableSerialization<T>.Serializer.Type);
|
||||||
if (NetworkVariableSerialization<T>.Type == CollectionItemType.Unmanaged)
|
if (NetworkVariableSerialization<T>.Serializer.Type == NetworkVariableType.Unmanaged)
|
||||||
{
|
{
|
||||||
// Write the size of the unmanaged serialized type as it has a fixed size. This allows the CMB runtime to correctly read the unmanged type.
|
// Write the size of the unmanaged serialized type as it has a fixed size. This allows the CMB runtime to correctly read the unmanged type.
|
||||||
var placeholder = new T();
|
var placeholder = new T();
|
||||||
var startPos = writer.Position;
|
var startPos = writer.Position;
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref placeholder);
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref placeholder);
|
||||||
var size = writer.Position - startPos;
|
var size = writer.Position - startPos;
|
||||||
writer.Seek(startPos);
|
writer.Seek(startPos);
|
||||||
BytePacker.WriteValueBitPacked(writer, size);
|
BytePacker.WriteValueBitPacked(writer, size);
|
||||||
@@ -148,7 +148,7 @@ namespace Unity.Netcode
|
|||||||
writer.WriteValueSafe((ushort)m_List.Length);
|
writer.WriteValueSafe((ushort)m_List.Length);
|
||||||
for (int i = 0; i < m_List.Length; i++)
|
for (int i = 0; i < m_List.Length; i++)
|
||||||
{
|
{
|
||||||
NetworkVariableSerialization<T>.Write(writer, ref m_List.ElementAt(i));
|
NetworkVariableSerialization<T>.Serializer.Write(writer, ref m_List.ElementAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,9 +158,9 @@ namespace Unity.Netcode
|
|||||||
m_List.Clear();
|
m_List.Clear();
|
||||||
if (m_NetworkManager.DistributedAuthorityMode)
|
if (m_NetworkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
// Collection item type is used by the CMB rust service, drop value here.
|
SerializationTools.ReadType(reader, NetworkVariableSerialization<T>.Serializer);
|
||||||
reader.ReadValueSafe(out CollectionItemType type);
|
// Collection item type is used by the DA server, drop value here.
|
||||||
if (type == CollectionItemType.Unmanaged)
|
if (NetworkVariableSerialization<T>.Serializer.Type == NetworkVariableType.Unmanaged)
|
||||||
{
|
{
|
||||||
ByteUnpacker.ReadValueBitPacked(reader, out int _);
|
ByteUnpacker.ReadValueBitPacked(reader, out int _);
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ namespace Unity.Netcode
|
|||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var value = new T();
|
var value = new T();
|
||||||
NetworkVariableSerialization<T>.Read(reader, ref value);
|
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
|
||||||
m_List.Add(value);
|
m_List.Add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ namespace Unity.Netcode
|
|||||||
case NetworkListEvent<T>.EventType.Add:
|
case NetworkListEvent<T>.EventType.Add:
|
||||||
{
|
{
|
||||||
var value = new T();
|
var value = new T();
|
||||||
NetworkVariableSerialization<T>.Read(reader, ref value);
|
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
|
||||||
m_List.Add(value);
|
m_List.Add(value);
|
||||||
|
|
||||||
if (OnListChanged != null)
|
if (OnListChanged != null)
|
||||||
@@ -215,7 +215,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
ByteUnpacker.ReadValueBitPacked(reader, out int index);
|
ByteUnpacker.ReadValueBitPacked(reader, out int index);
|
||||||
var value = new T();
|
var value = new T();
|
||||||
NetworkVariableSerialization<T>.Read(reader, ref value);
|
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
|
||||||
|
|
||||||
if (index < m_List.Length)
|
if (index < m_List.Length)
|
||||||
{
|
{
|
||||||
@@ -252,7 +252,7 @@ namespace Unity.Netcode
|
|||||||
case NetworkListEvent<T>.EventType.Remove:
|
case NetworkListEvent<T>.EventType.Remove:
|
||||||
{
|
{
|
||||||
var value = new T();
|
var value = new T();
|
||||||
NetworkVariableSerialization<T>.Read(reader, ref value);
|
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
|
||||||
int index = m_List.IndexOf(value);
|
int index = m_List.IndexOf(value);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
@@ -315,7 +315,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
ByteUnpacker.ReadValueBitPacked(reader, out int index);
|
ByteUnpacker.ReadValueBitPacked(reader, out int index);
|
||||||
var value = new T();
|
var value = new T();
|
||||||
NetworkVariableSerialization<T>.Read(reader, ref value);
|
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
|
||||||
if (index >= m_List.Length)
|
if (index >= m_List.Length)
|
||||||
{
|
{
|
||||||
throw new Exception("Shouldn't be here, index is higher than list length");
|
throw new Exception("Shouldn't be here, index is higher than list length");
|
||||||
@@ -393,7 +393,8 @@ namespace Unity.Netcode
|
|||||||
// check write permissions
|
// check write permissions
|
||||||
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
LogWritePermissionError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_List.Add(item);
|
m_List.Add(item);
|
||||||
@@ -414,7 +415,8 @@ namespace Unity.Netcode
|
|||||||
// check write permissions
|
// check write permissions
|
||||||
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
LogWritePermissionError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_List.Clear();
|
m_List.Clear();
|
||||||
@@ -440,7 +442,8 @@ namespace Unity.Netcode
|
|||||||
// check write permissions
|
// check write permissions
|
||||||
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
LogWritePermissionError();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = m_List.IndexOf(item);
|
int index = m_List.IndexOf(item);
|
||||||
@@ -475,7 +478,8 @@ namespace Unity.Netcode
|
|||||||
// check write permissions
|
// check write permissions
|
||||||
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
LogWritePermissionError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < m_List.Length)
|
if (index < m_List.Length)
|
||||||
@@ -520,6 +524,8 @@ namespace Unity.Netcode
|
|||||||
HandleAddListEvent(listEvent);
|
HandleAddListEvent(listEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public T this[int index]
|
public T this[int index]
|
||||||
{
|
{
|
||||||
@@ -529,7 +535,8 @@ namespace Unity.Netcode
|
|||||||
// check write permissions
|
// check write permissions
|
||||||
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
if (!CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
LogWritePermissionError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousValue = m_List[index];
|
var previousValue = m_List[index];
|
||||||
|
|||||||
@@ -94,27 +94,59 @@ namespace Unity.Netcode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The value of the NetworkVariable container
|
/// The value of the NetworkVariable container
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When assigning collections to <see cref="Value"/>, unless it is a completely new collection this will not
|
||||||
|
/// detect any deltas with most managed collection classes since assignment of one collection value to another
|
||||||
|
/// is actually just a reference to the collection itself. <br />
|
||||||
|
/// To detect deltas in a collection, you should invoke <see cref="CheckDirtyState"/> after making modifications to the collection.
|
||||||
|
/// </remarks>
|
||||||
public virtual T Value
|
public virtual T Value
|
||||||
{
|
{
|
||||||
get => m_InternalValue;
|
get => m_InternalValue;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
// Compare bitwise
|
if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId))
|
||||||
if (NetworkVariableSerialization<T>.AreEqual(ref m_InternalValue, ref value))
|
|
||||||
{
|
{
|
||||||
|
LogWritePermissionError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId))
|
// Compare the Value being applied to the current value
|
||||||
|
if (!NetworkVariableSerialization<T>.AreEqual(ref m_InternalValue, ref value))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"[Client-{m_NetworkManager.LocalClientId}][{m_NetworkBehaviour.name}][{Name}] Write permissions ({WritePerm}) for this client instance is not allowed!");
|
T previousValue = m_InternalValue;
|
||||||
|
m_InternalValue = value;
|
||||||
|
SetDirty(true);
|
||||||
|
m_IsDisposed = false;
|
||||||
|
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set(value);
|
|
||||||
m_IsDisposed = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke this method to check if a collection's items are dirty.
|
||||||
|
/// The default behavior is to exit early if the <see cref="NetworkVariable{T}"/> is already dirty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forceCheck"> when true, this check will force a full item collection check even if the NetworkVariable is already dirty</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is to be used as a way to check if a <see cref="NetworkVariable{T}"/> containing a managed collection has any changees to the collection items.<br />
|
||||||
|
/// If you invoked this when a collection is dirty, it will not trigger the <see cref="OnValueChanged"/> unless you set <param name="forceCheck"/> to true. <br />
|
||||||
|
/// </remarks>
|
||||||
|
public bool CheckDirtyState(bool forceCheck = false)
|
||||||
|
{
|
||||||
|
var isDirty = base.IsDirty();
|
||||||
|
|
||||||
|
// Compare the previous with the current if not dirty or forcing a check.
|
||||||
|
if ((!isDirty || forceCheck) && !NetworkVariableSerialization<T>.AreEqual(ref m_PreviousValue, ref m_InternalValue))
|
||||||
|
{
|
||||||
|
SetDirty(true);
|
||||||
|
OnValueChanged?.Invoke(m_PreviousValue, m_InternalValue);
|
||||||
|
m_IsDisposed = false;
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
return isDirty;
|
||||||
|
}
|
||||||
|
|
||||||
internal ref T RefValue()
|
internal ref T RefValue()
|
||||||
{
|
{
|
||||||
return ref m_InternalValue;
|
return ref m_InternalValue;
|
||||||
@@ -193,19 +225,6 @@ namespace Unity.Netcode
|
|||||||
base.ResetDirty();
|
base.ResetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the <see cref="Value"/>, marks the <see cref="NetworkVariable{T}"/> dirty, and invokes the <see cref="OnValueChanged"/> callback
|
|
||||||
/// if there are subscribers to that event.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">the new value of type `T` to be set/></param>
|
|
||||||
private protected void Set(T value)
|
|
||||||
{
|
|
||||||
SetDirty(true);
|
|
||||||
T previousValue = m_InternalValue;
|
|
||||||
m_InternalValue = value;
|
|
||||||
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes the variable to the writer
|
/// Writes the variable to the writer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -222,20 +241,22 @@ namespace Unity.Netcode
|
|||||||
/// <param name="keepDirtyDelta">Whether or not the container should keep the dirty delta, or mark the delta as consumed</param>
|
/// <param name="keepDirtyDelta">Whether or not the container should keep the dirty delta, or mark the delta as consumed</param>
|
||||||
public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
|
public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
|
||||||
{
|
{
|
||||||
|
// In order to get managed collections to properly have a previous and current value, we have to
|
||||||
|
// duplicate the collection at this point before making any modifications to the current.
|
||||||
|
m_HasPreviousValue = true;
|
||||||
|
NetworkVariableSerialization<T>.Duplicate(m_InternalValue, ref m_PreviousValue);
|
||||||
|
NetworkVariableSerialization<T>.ReadDelta(reader, ref m_InternalValue);
|
||||||
|
|
||||||
// todo:
|
// todo:
|
||||||
// keepDirtyDelta marks a variable received as dirty and causes the server to send the value to clients
|
// keepDirtyDelta marks a variable received as dirty and causes the server to send the value to clients
|
||||||
// In a prefect world, whether a variable was A) modified locally or B) received and needs retransmit
|
// In a prefect world, whether a variable was A) modified locally or B) received and needs retransmit
|
||||||
// would be stored in different fields
|
// would be stored in different fields
|
||||||
|
|
||||||
T previousValue = m_InternalValue;
|
|
||||||
NetworkVariableSerialization<T>.ReadDelta(reader, ref m_InternalValue);
|
|
||||||
|
|
||||||
if (keepDirtyDelta)
|
if (keepDirtyDelta)
|
||||||
{
|
{
|
||||||
SetDirty(true);
|
SetDirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
OnValueChanged?.Invoke(m_PreviousValue, m_InternalValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -35,7 +35,17 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
private NetworkManager m_InternalNetworkManager;
|
private NetworkManager m_InternalNetworkManager;
|
||||||
|
|
||||||
internal virtual NetworkVariableType Type => NetworkVariableType.Custom;
|
internal virtual NetworkVariableType Type => NetworkVariableType.Unknown;
|
||||||
|
|
||||||
|
internal string GetWritePermissionError()
|
||||||
|
{
|
||||||
|
return $"|Client-{m_NetworkManager.LocalClientId}|{m_NetworkBehaviour.name}|{Name}| Write permissions ({WritePerm}) for this client instance is not allowed!";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void LogWritePermissionError()
|
||||||
|
{
|
||||||
|
Debug.LogError(GetWritePermissionError());
|
||||||
|
}
|
||||||
|
|
||||||
private protected NetworkManager m_NetworkManager
|
private protected NetworkManager m_NetworkManager
|
||||||
{
|
{
|
||||||
@@ -254,6 +264,11 @@ namespace Unity.Netcode
|
|||||||
/// <returns>Whether or not the client has permission to read</returns>
|
/// <returns>Whether or not the client has permission to read</returns>
|
||||||
public bool CanClientRead(ulong clientId)
|
public bool CanClientRead(ulong clientId)
|
||||||
{
|
{
|
||||||
|
if (!m_NetworkBehaviour)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// When in distributed authority mode, everyone can read (but only the owner can write)
|
// When in distributed authority mode, everyone can read (but only the owner can write)
|
||||||
if (m_NetworkManager != null && m_NetworkManager.DistributedAuthorityMode)
|
if (m_NetworkManager != null && m_NetworkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
@@ -276,6 +291,11 @@ namespace Unity.Netcode
|
|||||||
/// <returns>Whether or not the client has permission to write</returns>
|
/// <returns>Whether or not the client has permission to write</returns>
|
||||||
public bool CanClientWrite(ulong clientId)
|
public bool CanClientWrite(ulong clientId)
|
||||||
{
|
{
|
||||||
|
if (!m_NetworkBehaviour)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (WritePerm)
|
switch (WritePerm)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@@ -311,7 +331,6 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The stream to read the state from</param>
|
/// <param name="reader">The stream to read the state from</param>
|
||||||
public abstract void ReadField(FastBufferReader reader);
|
public abstract void ReadField(FastBufferReader reader);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads delta from the reader and applies them to the internal value
|
/// Reads delta from the reader and applies them to the internal value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -327,47 +346,4 @@ namespace Unity.Netcode
|
|||||||
m_InternalNetworkManager = null;
|
m_InternalNetworkManager = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enum representing the different types of Network Variables.
|
|
||||||
/// </summary>
|
|
||||||
public enum NetworkVariableType : byte
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Value
|
|
||||||
/// Used for all of the basic NetworkVariables that contain a single value
|
|
||||||
/// </summary>
|
|
||||||
Value = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom
|
|
||||||
/// For any custom implemented extension of the NetworkVariableBase
|
|
||||||
/// </summary>
|
|
||||||
Custom = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// NetworkList
|
|
||||||
/// </summary>
|
|
||||||
NetworkList = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CollectionItemType : byte
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// For any type that is not valid inside a NetworkVariable collection
|
|
||||||
/// </summary>
|
|
||||||
Unknown = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The following types are valid types inside of NetworkVariable collections
|
|
||||||
/// </summary>
|
|
||||||
Short = 1,
|
|
||||||
UShort = 2,
|
|
||||||
Int = 3,
|
|
||||||
UInt = 4,
|
|
||||||
Long = 5,
|
|
||||||
ULong = 6,
|
|
||||||
Unmanaged = 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
40
Runtime/NetworkVariable/NetworkVariableTypes.cs
Normal file
40
Runtime/NetworkVariable/NetworkVariableTypes.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Unity.Netcode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enum representing the different types of Network Variables that can be sent over the network.
|
||||||
|
/// The values cannot be changed, as they are used to serialize and deserialize variables on the DA server.
|
||||||
|
/// Adding new variables should be done by adding new values to the end of the enum
|
||||||
|
/// using the next free value.
|
||||||
|
/// </summary>
|
||||||
|
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
/// Add any new Variable types to this table at the END with incremented index value
|
||||||
|
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
internal enum NetworkVariableType : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Value
|
||||||
|
/// Used for all of the basic NetworkVariables that contain a single value
|
||||||
|
/// </summary>
|
||||||
|
Value = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// For any type that is not known at runtime
|
||||||
|
/// </summary>
|
||||||
|
Unknown = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// NetworkList
|
||||||
|
/// </summary>
|
||||||
|
NetworkList = 2,
|
||||||
|
|
||||||
|
// The following types are valid types inside of NetworkVariable collections
|
||||||
|
Short = 11,
|
||||||
|
UShort = 12,
|
||||||
|
Int = 13,
|
||||||
|
UInt = 14,
|
||||||
|
Long = 15,
|
||||||
|
ULong = 16,
|
||||||
|
Unmanaged = 17,
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Runtime/NetworkVariable/NetworkVariableTypes.cs.meta
Normal file
3
Runtime/NetworkVariable/NetworkVariableTypes.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: df4a4005f1c842669f94a404019400ed
|
||||||
|
timeCreated: 1718292058
|
||||||
@@ -14,6 +14,9 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class FallbackSerializer<T> : INetworkVariableSerializer<T>
|
internal class FallbackSerializer<T> : INetworkVariableSerializer<T>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Unknown;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
private void ThrowArgumentError()
|
private void ThrowArgumentError()
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Serialization has not been generated for type {typeof(T).FullName}. This can be addressed by adding a [{nameof(GenerateSerializationForGenericParameterAttribute)}] to your generic class that serializes this value (if you are using one), adding [{nameof(GenerateSerializationForTypeAttribute)}(typeof({typeof(T).FullName})] to the class or method that is attempting to serialize it, or creating a field on a {nameof(NetworkBehaviour)} of type {nameof(NetworkVariable<T>)}. If this error continues to appear after doing one of those things and this is a type you can change, then either implement {nameof(INetworkSerializable)} or mark it as serializable by memcpy by adding {nameof(INetworkSerializeByMemcpy)} to its interface list to enable automatic serialization generation. If not, assign serialization code to {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.WriteValue)}, {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.ReadValue)}, and {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.DuplicateValue)}, or if it's serializable by memcpy (contains no pointers), wrap it in {typeof(ForceNetworkSerializeByMemcpy<>).Name}.");
|
throw new ArgumentException($"Serialization has not been generated for type {typeof(T).FullName}. This can be addressed by adding a [{nameof(GenerateSerializationForGenericParameterAttribute)}] to your generic class that serializes this value (if you are using one), adding [{nameof(GenerateSerializationForTypeAttribute)}(typeof({typeof(T).FullName})] to the class or method that is attempting to serialize it, or creating a field on a {nameof(NetworkBehaviour)} of type {nameof(NetworkVariable<T>)}. If this error continues to appear after doing one of those things and this is a type you can change, then either implement {nameof(INetworkSerializable)} or mark it as serializable by memcpy by adding {nameof(INetworkSerializeByMemcpy)} to its interface list to enable automatic serialization generation. If not, assign serialization code to {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.WriteValue)}, {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.ReadValue)}, and {nameof(UserNetworkVariableSerialization<T>)}.{nameof(UserNetworkVariableSerialization<T>.DuplicateValue)}, or if it's serializable by memcpy (contains no pointers), wrap it in {typeof(ForceNetworkSerializeByMemcpy<>).Name}.");
|
||||||
@@ -79,6 +82,11 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
UserNetworkVariableSerialization<T>.DuplicateValue(value, ref duplicatedValue);
|
UserNetworkVariableSerialization<T>.DuplicateValue(value, ref duplicatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) => ThrowArgumentError();
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value) => ThrowArgumentError();
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => ThrowArgumentError();
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => ThrowArgumentError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeAccessModifiersILPP will make this `public`
|
// RuntimeAccessModifiersILPP will make this `public`
|
||||||
|
|||||||
@@ -3,11 +3,27 @@ using Unity.Collections;
|
|||||||
namespace Unity.Netcode
|
namespace Unity.Netcode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface used by NetworkVariables to serialize them
|
/// Interface used by NetworkVariables to serialize them with additional information for the DA runtime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
///
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal interface INetworkVariableSerializer<T>
|
internal interface IDistributedAuthoritySerializer<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Type tells the DA server how to parse this type.
|
||||||
|
/// The user should never be able to override this value, as it is meaningful for the DA server
|
||||||
|
/// </summary>
|
||||||
|
public NetworkVariableType Type { get; }
|
||||||
|
public bool IsDistributedAuthorityOptimized { get; }
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value);
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value);
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
internal interface INetworkVariableSerializer<T> : IDistributedAuthoritySerializer<T>
|
||||||
{
|
{
|
||||||
// Write has to be taken by ref here because of INetworkSerializable
|
// Write has to be taken by ref here because of INetworkSerializable
|
||||||
// Open Instance Delegates (pointers to methods without an instance attached to them)
|
// Open Instance Delegates (pointers to methods without an instance attached to them)
|
||||||
|
|||||||
@@ -16,12 +16,6 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
internal static bool IsDistributedAuthority => NetworkManager.IsDistributedAuthority;
|
internal static bool IsDistributedAuthority => NetworkManager.IsDistributedAuthority;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The collection item type tells the CMB server how to read the bytes of each item in the collection
|
|
||||||
/// </summary>
|
|
||||||
/// DANGO-EXP TODO: Determine if this is distributed authority only and impacts of this in client-server
|
|
||||||
internal static CollectionItemType Type = CollectionItemType.Unknown;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A callback to check if two values are equal.
|
/// A callback to check if two values are equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -59,7 +53,20 @@ namespace Unity.Netcode
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public static void Write(FastBufferWriter writer, ref T value)
|
public static void Write(FastBufferWriter writer, ref T value)
|
||||||
{
|
{
|
||||||
Serializer.Write(writer, ref value);
|
if (IsDistributedAuthority)
|
||||||
|
{
|
||||||
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||||
|
if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized)
|
||||||
|
{
|
||||||
|
NetworkManager.LogSerializedTypeNotOptimized<T>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Serializer.WriteDistributedAuthority(writer, ref value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serializer.Write(writer, ref value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -84,7 +91,14 @@ namespace Unity.Netcode
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public static void Read(FastBufferReader reader, ref T value)
|
public static void Read(FastBufferReader reader, ref T value)
|
||||||
{
|
{
|
||||||
Serializer.Read(reader, ref value);
|
if (IsDistributedAuthority)
|
||||||
|
{
|
||||||
|
Serializer.ReadDistributedAuthority(reader, ref value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serializer.Read(reader, ref value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -106,7 +120,20 @@ namespace Unity.Netcode
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public static void WriteDelta(FastBufferWriter writer, ref T value, ref T previousValue)
|
public static void WriteDelta(FastBufferWriter writer, ref T value, ref T previousValue)
|
||||||
{
|
{
|
||||||
Serializer.WriteDelta(writer, ref value, ref previousValue);
|
if (IsDistributedAuthority)
|
||||||
|
{
|
||||||
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||||
|
if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized)
|
||||||
|
{
|
||||||
|
NetworkManager.LogSerializedTypeNotOptimized<T>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Serializer.WriteDeltaDistributedAuthority(writer, ref value, ref previousValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serializer.WriteDelta(writer, ref value, ref previousValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -131,7 +158,14 @@ namespace Unity.Netcode
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public static void ReadDelta(FastBufferReader reader, ref T value)
|
public static void ReadDelta(FastBufferReader reader, ref T value)
|
||||||
{
|
{
|
||||||
Serializer.ReadDelta(reader, ref value);
|
if (IsDistributedAuthority)
|
||||||
|
{
|
||||||
|
Serializer.ReadDeltaDistributedAuthority(reader, ref value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serializer.ReadDelta(reader, ref value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -38,14 +38,6 @@ namespace Unity.Netcode
|
|||||||
NetworkVariableSerialization<long>.AreEqual = NetworkVariableEquality<long>.ValueEquals;
|
NetworkVariableSerialization<long>.AreEqual = NetworkVariableEquality<long>.ValueEquals;
|
||||||
NetworkVariableSerialization<ulong>.Serializer = new UlongSerializer();
|
NetworkVariableSerialization<ulong>.Serializer = new UlongSerializer();
|
||||||
NetworkVariableSerialization<ulong>.AreEqual = NetworkVariableEquality<ulong>.ValueEquals;
|
NetworkVariableSerialization<ulong>.AreEqual = NetworkVariableEquality<ulong>.ValueEquals;
|
||||||
|
|
||||||
// DANGO-EXP TODO: Determine if this is distributed authority only and impacts of this in client-server
|
|
||||||
NetworkVariableSerialization<short>.Type = CollectionItemType.Short;
|
|
||||||
NetworkVariableSerialization<ushort>.Type = CollectionItemType.UShort;
|
|
||||||
NetworkVariableSerialization<int>.Type = CollectionItemType.Int;
|
|
||||||
NetworkVariableSerialization<uint>.Type = CollectionItemType.UInt;
|
|
||||||
NetworkVariableSerialization<long>.Type = CollectionItemType.Long;
|
|
||||||
NetworkVariableSerialization<ulong>.Type = CollectionItemType.ULong;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,8 +47,6 @@ namespace Unity.Netcode
|
|||||||
public static void InitializeSerializer_UnmanagedByMemcpy<T>() where T : unmanaged
|
public static void InitializeSerializer_UnmanagedByMemcpy<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
NetworkVariableSerialization<T>.Serializer = new UnmanagedTypeSerializer<T>();
|
NetworkVariableSerialization<T>.Serializer = new UnmanagedTypeSerializer<T>();
|
||||||
// DANGO-EXP TODO: Determine if this is distributed authority only and impacts of this in client-server
|
|
||||||
NetworkVariableSerialization<T>.Type = CollectionItemType.Unmanaged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -10,6 +10,21 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class ShortSerializer : INetworkVariableSerializer<short>
|
internal class ShortSerializer : INetworkVariableSerializer<short>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Short;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref short value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref short value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref short value, ref short previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref short value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref short value)
|
public void Write(FastBufferWriter writer, ref short value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -46,6 +61,20 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class UshortSerializer : INetworkVariableSerializer<ushort>
|
internal class UshortSerializer : INetworkVariableSerializer<ushort>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.UShort;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref ushort value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref ushort value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref ushort value, ref ushort previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref ushort value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref ushort value)
|
public void Write(FastBufferWriter writer, ref ushort value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -82,6 +111,20 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class IntSerializer : INetworkVariableSerializer<int>
|
internal class IntSerializer : INetworkVariableSerializer<int>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Int;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref int value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref int value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref int value, ref int previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref int value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref int value)
|
public void Write(FastBufferWriter writer, ref int value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -118,6 +161,20 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class UintSerializer : INetworkVariableSerializer<uint>
|
internal class UintSerializer : INetworkVariableSerializer<uint>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.UInt;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref uint value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref uint value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref uint value, ref uint previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref uint value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref uint value)
|
public void Write(FastBufferWriter writer, ref uint value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -154,6 +211,20 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class LongSerializer : INetworkVariableSerializer<long>
|
internal class LongSerializer : INetworkVariableSerializer<long>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Long;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref long value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref long value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref long value, ref long previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref long value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref long value)
|
public void Write(FastBufferWriter writer, ref long value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -190,6 +261,21 @@ namespace Unity.Netcode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class UlongSerializer : INetworkVariableSerializer<ulong>
|
internal class UlongSerializer : INetworkVariableSerializer<ulong>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.ULong;
|
||||||
|
public bool IsDistributedAuthorityOptimized => true;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref ulong value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref ulong value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref ulong value, ref ulong previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref ulong value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref ulong value)
|
public void Write(FastBufferWriter writer, ref ulong value)
|
||||||
{
|
{
|
||||||
BytePacker.WriteValueBitPacked(writer, value);
|
BytePacker.WriteValueBitPacked(writer, value);
|
||||||
@@ -231,6 +317,21 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class UnmanagedTypeSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged
|
internal class UnmanagedTypeSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Unmanaged;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref T value)
|
public void Write(FastBufferWriter writer, ref T value)
|
||||||
{
|
{
|
||||||
writer.WriteUnmanagedSafe(value);
|
writer.WriteUnmanagedSafe(value);
|
||||||
@@ -264,6 +365,20 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
internal class ListSerializer<T> : INetworkVariableSerializer<List<T>>
|
internal class ListSerializer<T> : INetworkVariableSerializer<List<T>>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref List<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref List<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref List<T> value, ref List<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref List<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref List<T> value)
|
public void Write(FastBufferWriter writer, ref List<T> value)
|
||||||
{
|
{
|
||||||
var isNull = value == null;
|
var isNull = value == null;
|
||||||
@@ -343,13 +458,30 @@ namespace Unity.Netcode
|
|||||||
duplicatedValue.Clear();
|
duplicatedValue.Clear();
|
||||||
foreach (var item in value)
|
foreach (var item in value)
|
||||||
{
|
{
|
||||||
duplicatedValue.Add(item);
|
// This handles the nested list scenario List<List<T>>
|
||||||
|
T subValue = default;
|
||||||
|
NetworkVariableSerialization<T>.Duplicate(item, ref subValue);
|
||||||
|
duplicatedValue.Add(subValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class HashSetSerializer<T> : INetworkVariableSerializer<HashSet<T>> where T : IEquatable<T>
|
internal class HashSetSerializer<T> : INetworkVariableSerializer<HashSet<T>> where T : IEquatable<T>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref HashSet<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref HashSet<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref HashSet<T> value, ref HashSet<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref HashSet<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref HashSet<T> value)
|
public void Write(FastBufferWriter writer, ref HashSet<T> value)
|
||||||
{
|
{
|
||||||
var isNull = value == null;
|
var isNull = value == null;
|
||||||
@@ -419,6 +551,9 @@ namespace Unity.Netcode
|
|||||||
duplicatedValue.Clear();
|
duplicatedValue.Clear();
|
||||||
foreach (var item in value)
|
foreach (var item in value)
|
||||||
{
|
{
|
||||||
|
// Handles nested HashSets
|
||||||
|
T subValue = default;
|
||||||
|
NetworkVariableSerialization<T>.Duplicate(item, ref subValue);
|
||||||
duplicatedValue.Add(item);
|
duplicatedValue.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,6 +563,20 @@ namespace Unity.Netcode
|
|||||||
internal class DictionarySerializer<TKey, TVal> : INetworkVariableSerializer<Dictionary<TKey, TVal>>
|
internal class DictionarySerializer<TKey, TVal> : INetworkVariableSerializer<Dictionary<TKey, TVal>>
|
||||||
where TKey : IEquatable<TKey>
|
where TKey : IEquatable<TKey>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref Dictionary<TKey, TVal> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref Dictionary<TKey, TVal> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref Dictionary<TKey, TVal> value, ref Dictionary<TKey, TVal> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref Dictionary<TKey, TVal> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref Dictionary<TKey, TVal> value)
|
public void Write(FastBufferWriter writer, ref Dictionary<TKey, TVal> value)
|
||||||
{
|
{
|
||||||
var isNull = value == null;
|
var isNull = value == null;
|
||||||
@@ -498,13 +647,32 @@ namespace Unity.Netcode
|
|||||||
duplicatedValue.Clear();
|
duplicatedValue.Clear();
|
||||||
foreach (var item in value)
|
foreach (var item in value)
|
||||||
{
|
{
|
||||||
duplicatedValue.Add(item.Key, item.Value);
|
// Handles nested dictionaries
|
||||||
|
TKey subKey = default;
|
||||||
|
TVal subValue = default;
|
||||||
|
NetworkVariableSerialization<TKey>.Duplicate(item.Key, ref subKey);
|
||||||
|
NetworkVariableSerialization<TVal>.Duplicate(item.Value, ref subValue);
|
||||||
|
duplicatedValue.Add(subKey, subValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UnmanagedArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged
|
internal class UnmanagedArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value, ref NativeArray<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteUnmanagedSafe(value);
|
writer.WriteUnmanagedSafe(value);
|
||||||
@@ -550,6 +718,20 @@ namespace Unity.Netcode
|
|||||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||||
internal class UnmanagedListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged
|
internal class UnmanagedListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value, ref NativeList<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteUnmanagedSafe(value);
|
writer.WriteUnmanagedSafe(value);
|
||||||
@@ -593,6 +775,21 @@ namespace Unity.Netcode
|
|||||||
|
|
||||||
internal class NativeHashSetSerializer<T> : INetworkVariableSerializer<NativeHashSet<T>> where T : unmanaged, IEquatable<T>
|
internal class NativeHashSetSerializer<T> : INetworkVariableSerializer<NativeHashSet<T>> where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeHashSet<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeHashSet<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeHashSet<T> value, ref NativeHashSet<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeHashSet<T> value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref NativeHashSet<T> value)
|
public void Write(FastBufferWriter writer, ref NativeHashSet<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe(value);
|
writer.WriteValueSafe(value);
|
||||||
@@ -638,6 +835,21 @@ namespace Unity.Netcode
|
|||||||
where TKey : unmanaged, IEquatable<TKey>
|
where TKey : unmanaged, IEquatable<TKey>
|
||||||
where TVal : unmanaged
|
where TVal : unmanaged
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeHashMap<TKey, TVal> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeHashMap<TKey, TVal> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeHashMap<TKey, TVal> value, ref NativeHashMap<TKey, TVal> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeHashMap<TKey, TVal> value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref NativeHashMap<TKey, TVal> value)
|
public void Write(FastBufferWriter writer, ref NativeHashMap<TKey, TVal> value)
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe(value);
|
writer.WriteValueSafe(value);
|
||||||
@@ -680,12 +892,25 @@ namespace Unity.Netcode
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Serializer for FixedStrings
|
/// Serializer for FixedStrings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class FixedStringSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
internal class FixedStringSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
||||||
{
|
{
|
||||||
// The item type can only be bytes for fixedStrings, so the DA runtime doesn't need details on it
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref T value)
|
public void Write(FastBufferWriter writer, ref T value)
|
||||||
{
|
{
|
||||||
@@ -710,7 +935,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
var val = value[i];
|
var val = value[i];
|
||||||
var prevVal = previousValue[i];
|
var prevVal = previousValue[i];
|
||||||
if (!NetworkVariableSerialization<byte>.AreEqual(ref val, ref prevVal))
|
if (val != prevVal)
|
||||||
{
|
{
|
||||||
++numChanges;
|
++numChanges;
|
||||||
changes.Set(i);
|
changes.Set(i);
|
||||||
@@ -731,23 +956,15 @@ namespace Unity.Netcode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteByte(0); // Flag that we're sending a delta
|
writer.WriteByteSafe(0); // Flag that we're sending a delta
|
||||||
BytePacker.WriteValuePacked(writer, value.Length);
|
BytePacker.WriteValuePacked(writer, value.Length);
|
||||||
writer.WriteValueSafe(changes);
|
writer.WriteValueSafe(changes);
|
||||||
var ptr = value.GetUnsafePtr();
|
var ptr = value.GetUnsafePtr();
|
||||||
var prevPtr = previousValue.GetUnsafePtr();
|
|
||||||
for (var i = 0; i < value.Length; ++i)
|
for (var i = 0; i < value.Length; ++i)
|
||||||
{
|
{
|
||||||
if (changes.IsSet(i))
|
if (changes.IsSet(i))
|
||||||
{
|
{
|
||||||
if (i < previousValue.Length)
|
writer.WriteByteSafe(ptr[i]);
|
||||||
{
|
|
||||||
NetworkVariableSerialization<byte>.WriteDelta(writer, ref ptr[i], ref prevPtr[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetworkVariableSerialization<byte>.Write(writer, ref ptr[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,7 +996,7 @@ namespace Unity.Netcode
|
|||||||
{
|
{
|
||||||
if (changes.IsSet(i))
|
if (changes.IsSet(i))
|
||||||
{
|
{
|
||||||
reader.ReadByte(out ptr[i]);
|
reader.ReadByteSafe(out ptr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -802,6 +1019,20 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class FixedStringArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
internal class FixedStringArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value, ref NativeArray<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe(value);
|
writer.WriteValueSafe(value);
|
||||||
@@ -852,6 +1083,21 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class FixedStringListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
internal class FixedStringListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged, INativeList<byte>, IUTF8Bytes
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value, ref NativeList<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList<T> value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteValueSafe(value);
|
writer.WriteValueSafe(value);
|
||||||
@@ -899,6 +1145,21 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class UnmanagedNetworkSerializableSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged, INetworkSerializable
|
internal class UnmanagedNetworkSerializableSerializer<T> : INetworkVariableSerializer<T> where T : unmanaged, INetworkSerializable
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref T value)
|
public void Write(FastBufferWriter writer, ref T value)
|
||||||
{
|
{
|
||||||
var bufferSerializer = new BufferSerializer<BufferSerializerWriter>(new BufferSerializerWriter(writer));
|
var bufferSerializer = new BufferSerializer<BufferSerializerWriter>(new BufferSerializerWriter(writer));
|
||||||
@@ -951,6 +1212,20 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class UnmanagedNetworkSerializableArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged, INetworkSerializable
|
internal class UnmanagedNetworkSerializableArraySerializer<T> : INetworkVariableSerializer<NativeArray<T>> where T : unmanaged, INetworkSerializable
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray<T> value, ref NativeArray<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray<T> value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
public void Write(FastBufferWriter writer, ref NativeArray<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteNetworkSerializable(value);
|
writer.WriteNetworkSerializable(value);
|
||||||
@@ -1001,6 +1276,21 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class UnmanagedNetworkSerializableListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged, INetworkSerializable
|
internal class UnmanagedNetworkSerializableListSerializer<T> : INetworkVariableSerializer<NativeList<T>> where T : unmanaged, INetworkSerializable
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList<T> value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList<T> value, ref NativeList<T> previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList<T> value) => Read(reader, ref value);
|
||||||
|
|
||||||
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
public void Write(FastBufferWriter writer, ref NativeList<T> value)
|
||||||
{
|
{
|
||||||
writer.WriteNetworkSerializable(value);
|
writer.WriteNetworkSerializable(value);
|
||||||
@@ -1048,6 +1338,20 @@ namespace Unity.Netcode
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
internal class ManagedNetworkSerializableSerializer<T> : INetworkVariableSerializer<T> where T : class, INetworkSerializable, new()
|
internal class ManagedNetworkSerializableSerializer<T> : INetworkVariableSerializer<T> where T : class, INetworkSerializable, new()
|
||||||
{
|
{
|
||||||
|
public NetworkVariableType Type => NetworkVariableType.Value;
|
||||||
|
public bool IsDistributedAuthorityOptimized => false;
|
||||||
|
|
||||||
|
public void WriteDistributedAuthority(FastBufferWriter writer, ref T value)
|
||||||
|
{
|
||||||
|
Write(writer, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadDistributedAuthority(FastBufferReader reader, ref T value)
|
||||||
|
{
|
||||||
|
Read(reader, ref value);
|
||||||
|
}
|
||||||
|
public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value);
|
||||||
|
public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value);
|
||||||
public void Write(FastBufferWriter writer, ref T value)
|
public void Write(FastBufferWriter writer, ref T value)
|
||||||
{
|
{
|
||||||
var bufferSerializer = new BufferSerializer<BufferSerializerWriter>(new BufferSerializerWriter(writer));
|
var bufferSerializer = new BufferSerializer<BufferSerializerWriter>(new BufferSerializerWriter(writer));
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Unity.Netcode
|
||||||
|
{
|
||||||
|
|
||||||
|
internal static class SerializationTools
|
||||||
|
{
|
||||||
|
public delegate void WriteDelegate<T>(FastBufferWriter writer, ref T value);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void WriteWithSize<T>(WriteDelegate<T> writeMethod, FastBufferWriter writer, ref T value)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
// to pack here, we'd have to write data to a temporary buffer and copy it in - which
|
||||||
|
// isn't worth possibly saving one byte if and only if the data is less than 63 bytes long...
|
||||||
|
// The way we do packing, any value > 63 in a ushort will use the full 2 bytes to represent.
|
||||||
|
writer.WriteValueSafe((ushort)0);
|
||||||
|
var startPos = writer.Position;
|
||||||
|
writeMethod(writer, ref value);
|
||||||
|
var size = writer.Position - startPos;
|
||||||
|
writer.Seek(writePos);
|
||||||
|
writer.WriteValueSafe((ushort)size);
|
||||||
|
writer.Seek(startPos + size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void ReadDelegate<T>(FastBufferReader writer, ref T value);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void ReadWithSize<T>(ReadDelegate<T> readMethod, FastBufferReader reader, ref T value)
|
||||||
|
{
|
||||||
|
reader.ReadValueSafe(out ushort _);
|
||||||
|
readMethod(reader, ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void WriteType(FastBufferWriter writer, NetworkVariableType type) => writer.WriteValueSafe(type);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void ReadType<T>(FastBufferReader reader, INetworkVariableSerializer<T> serializer)
|
||||||
|
{
|
||||||
|
reader.ReadValueSafe(out NetworkVariableType type);
|
||||||
|
if (type != serializer.Type)
|
||||||
|
{
|
||||||
|
throw new SerializationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 52a4ce368df54b0a8887c08f3402bcd3
|
||||||
|
timeCreated: 1718300602
|
||||||
@@ -227,6 +227,11 @@ namespace Unity.Netcode
|
|||||||
foreach (var sceneToUnload in m_ScenesToUnload)
|
foreach (var sceneToUnload in m_ScenesToUnload)
|
||||||
{
|
{
|
||||||
SceneManager.UnloadSceneAsync(sceneToUnload);
|
SceneManager.UnloadSceneAsync(sceneToUnload);
|
||||||
|
// Update the ScenesLoaded when we unload scenes
|
||||||
|
if (sceneManager.ScenesLoaded.ContainsKey(sceneToUnload.handle))
|
||||||
|
{
|
||||||
|
sceneManager.ScenesLoaded.Remove(sceneToUnload.handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +333,9 @@ namespace Unity.Netcode
|
|||||||
public void SetClientSynchronizationMode(ref NetworkManager networkManager, LoadSceneMode mode)
|
public void SetClientSynchronizationMode(ref NetworkManager networkManager, LoadSceneMode mode)
|
||||||
{
|
{
|
||||||
var sceneManager = networkManager.SceneManager;
|
var sceneManager = networkManager.SceneManager;
|
||||||
// Don't let non-authority set this value
|
// In client-server, we don't let client's set this value.
|
||||||
if ((!networkManager.DistributedAuthorityMode && !networkManager.IsServer) || (networkManager.DistributedAuthorityMode && !networkManager.LocalClient.IsSessionOwner))
|
// In distributed authority, since session owner can be promoted clients can set this value
|
||||||
|
if (!networkManager.DistributedAuthorityMode && !networkManager.IsServer)
|
||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||||
{
|
{
|
||||||
@@ -338,7 +344,7 @@ namespace Unity.Netcode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else // Warn users if they are changing this after there are clients already connected and synchronized
|
else // Warn users if they are changing this after there are clients already connected and synchronized
|
||||||
if (networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode)
|
if (!networkManager.DistributedAuthorityMode && networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode)
|
||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -774,6 +774,7 @@ namespace Unity.Netcode
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This setting changes how clients handle scene loading when initially synchronizing with the server.<br />
|
/// This setting changes how clients handle scene loading when initially synchronizing with the server.<br />
|
||||||
/// The server or host should set this value as clients will automatically be synchronized with the server (or host) side.
|
/// The server or host should set this value as clients will automatically be synchronized with the server (or host) side.
|
||||||
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <b>LoadSceneMode.Single:</b> All currently loaded scenes on the client will be unloaded and the
|
/// <b>LoadSceneMode.Single:</b> All currently loaded scenes on the client will be unloaded and the
|
||||||
/// server's currently active scene will be loaded in single mode on the client unless it was already
|
/// server's currently active scene will be loaded in single mode on the client unless it was already
|
||||||
@@ -2406,16 +2407,6 @@ namespace Unity.Netcode
|
|||||||
NetworkManager.ConnectionManager.CreateAndSpawnPlayer(NetworkManager.LocalClientId);
|
NetworkManager.ConnectionManager.CreateAndSpawnPlayer(NetworkManager.LocalClientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is now synchronized and fully "connected". This also means the client can send "RPCs" at this time
|
|
||||||
NetworkManager.ConnectionManager.InvokeOnClientConnectedCallback(NetworkManager.LocalClientId);
|
|
||||||
|
|
||||||
// Notify the client that they have finished synchronizing
|
|
||||||
OnSceneEvent?.Invoke(new SceneEvent()
|
|
||||||
{
|
|
||||||
SceneEventType = sceneEventData.SceneEventType,
|
|
||||||
ClientId = NetworkManager.LocalClientId, // Client sent this to the server
|
|
||||||
});
|
|
||||||
|
|
||||||
// Process any SceneEventType.ObjectSceneChanged messages that
|
// Process any SceneEventType.ObjectSceneChanged messages that
|
||||||
// were deferred while synchronizing and migrate the associated
|
// were deferred while synchronizing and migrate the associated
|
||||||
// NetworkObjects to their newly assigned scenes.
|
// NetworkObjects to their newly assigned scenes.
|
||||||
@@ -2429,6 +2420,16 @@ namespace Unity.Netcode
|
|||||||
SceneManagerHandler.UnloadUnassignedScenes(NetworkManager);
|
SceneManagerHandler.UnloadUnassignedScenes(NetworkManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Client is now synchronized and fully "connected". This also means the client can send "RPCs" at this time
|
||||||
|
NetworkManager.ConnectionManager.InvokeOnClientConnectedCallback(NetworkManager.LocalClientId);
|
||||||
|
|
||||||
|
// Notify the client that they have finished synchronizing
|
||||||
|
OnSceneEvent?.Invoke(new SceneEvent()
|
||||||
|
{
|
||||||
|
SceneEventType = sceneEventData.SceneEventType,
|
||||||
|
ClientId = NetworkManager.LocalClientId, // Client sent this to the server
|
||||||
|
});
|
||||||
|
|
||||||
OnSynchronizeComplete?.Invoke(NetworkManager.LocalClientId);
|
OnSynchronizeComplete?.Invoke(NetworkManager.LocalClientId);
|
||||||
|
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||||
@@ -2436,10 +2437,7 @@ namespace Unity.Netcode
|
|||||||
NetworkLog.LogInfo($"[Client-{NetworkManager.LocalClientId}][Scene Management Enabled] Synchronization complete!");
|
NetworkLog.LogInfo($"[Client-{NetworkManager.LocalClientId}][Scene Management Enabled] Synchronization complete!");
|
||||||
}
|
}
|
||||||
// For convenience, notify all NetworkBehaviours that synchronization is complete.
|
// For convenience, notify all NetworkBehaviours that synchronization is complete.
|
||||||
foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList)
|
NetworkManager.SpawnManager.NotifyNetworkObjectsSynchronized();
|
||||||
{
|
|
||||||
networkObject.InternalNetworkSessionSynchronized();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NetworkManager.DistributedAuthorityMode && HasSceneAuthority() && IsRestoringSession)
|
if (NetworkManager.DistributedAuthorityMode && HasSceneAuthority() && IsRestoringSession)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -643,7 +643,7 @@ namespace Unity.Netcode
|
|||||||
return null;
|
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
|
// We only need to check for authority when running in client-server mode
|
||||||
if (!NetworkManager.IsServer && !NetworkManager.DistributedAuthorityMode)
|
if (!NetworkManager.IsServer && !NetworkManager.DistributedAuthorityMode)
|
||||||
{
|
{
|
||||||
@@ -1820,11 +1820,14 @@ namespace Unity.Netcode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var currentTick = serverTime.Tick;
|
var currentTick = serverTime.Tick;
|
||||||
var deferredCallbackObjects = DeferredDespawnObjects.Where((c) => c.HasDeferredDespawnCheck);
|
var deferredCallbackCount = DeferredDespawnObjects.Count();
|
||||||
var deferredCallbackCount = deferredCallbackObjects.Count();
|
for (int i = 0; i < deferredCallbackCount; i++)
|
||||||
for (int i = 0; i < deferredCallbackCount - 1; i++)
|
|
||||||
{
|
{
|
||||||
var deferredObjectEntry = deferredCallbackObjects.ElementAt(i);
|
var deferredObjectEntry = DeferredDespawnObjects[i];
|
||||||
|
if (!deferredObjectEntry.HasDeferredDespawnCheck)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var networkObject = SpawnedObjects[deferredObjectEntry.NetworkObjectId];
|
var networkObject = SpawnedObjects[deferredObjectEntry.NetworkObjectId];
|
||||||
// Double check to make sure user did not remove the callback
|
// Double check to make sure user did not remove the callback
|
||||||
if (networkObject.OnDeferredDespawnComplete != null)
|
if (networkObject.OnDeferredDespawnComplete != null)
|
||||||
@@ -1849,9 +1852,15 @@ namespace Unity.Netcode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var despawnObjects = DeferredDespawnObjects.Where((c) => c.TickToDespawn < currentTick).ToList();
|
// Parse backwards so we can remove objects as we parse through them
|
||||||
foreach (var deferredObjectEntry in despawnObjects)
|
for (int i = DeferredDespawnObjects.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
var deferredObjectEntry = DeferredDespawnObjects[i];
|
||||||
|
if (deferredObjectEntry.TickToDespawn >= currentTick)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SpawnedObjects.ContainsKey(deferredObjectEntry.NetworkObjectId))
|
if (!SpawnedObjects.ContainsKey(deferredObjectEntry.NetworkObjectId))
|
||||||
{
|
{
|
||||||
DeferredDespawnObjects.Remove(deferredObjectEntry);
|
DeferredDespawnObjects.Remove(deferredObjectEntry);
|
||||||
@@ -1863,5 +1872,16 @@ namespace Unity.Netcode
|
|||||||
DeferredDespawnObjects.Remove(deferredObjectEntry);
|
DeferredDespawnObjects.Remove(deferredObjectEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void NotifyNetworkObjectsSynchronized()
|
||||||
|
{
|
||||||
|
// Users could spawn NetworkObjects during these notifications.
|
||||||
|
// Create a separate list from the hashset to avoid list modification errors.
|
||||||
|
var spawnedObjects = SpawnedObjectsList.ToList();
|
||||||
|
foreach (var networkObject in spawnedObjects)
|
||||||
|
{
|
||||||
|
networkObject.InternalNetworkSessionSynchronized();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,6 +428,31 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
|
|
||||||
protected NetworkDriver m_Driver;
|
protected NetworkDriver m_Driver;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a reference to the <see cref="Networking.Transport.NetworkDriver"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>ref <see cref="Networking.Transport.NetworkDriver"/></returns>
|
||||||
|
public ref NetworkDriver GetNetworkDriver()
|
||||||
|
{
|
||||||
|
return ref m_Driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the local sytem's <see cref="NetworkEndpoint"/> that is assigned for the current network session.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the driver is not created it will return an invalid <see cref="NetworkEndpoint"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><see cref="NetworkEndpoint"/></returns>
|
||||||
|
public NetworkEndpoint GetLocalEndpoint()
|
||||||
|
{
|
||||||
|
if (m_Driver.IsCreated)
|
||||||
|
{
|
||||||
|
return m_Driver.GetLocalEndpoint();
|
||||||
|
}
|
||||||
|
return new NetworkEndpoint();
|
||||||
|
}
|
||||||
|
|
||||||
private PacketLossCache m_PacketLossCache = new PacketLossCache();
|
private PacketLossCache m_PacketLossCache = new PacketLossCache();
|
||||||
|
|
||||||
private State m_State = State.Disconnected;
|
private State m_State = State.Disconnected;
|
||||||
@@ -450,7 +475,10 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
|
|
||||||
private RelayServerData m_RelayServerData;
|
private RelayServerData m_RelayServerData;
|
||||||
|
|
||||||
internal NetworkManager NetworkManager;
|
/// <summary>
|
||||||
|
/// NetworkManager associated to this transport instance
|
||||||
|
/// </summary>
|
||||||
|
protected NetworkManager m_NetworkManager;
|
||||||
|
|
||||||
private IRealTimeProvider m_RealTimeProvider;
|
private IRealTimeProvider m_RealTimeProvider;
|
||||||
|
|
||||||
@@ -795,10 +823,10 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mtu = 0;
|
var mtu = 0;
|
||||||
if (NetworkManager)
|
if (m_NetworkManager)
|
||||||
{
|
{
|
||||||
var ngoClientId = NetworkManager.ConnectionManager.TransportIdToClientId(sendTarget.ClientId);
|
var ngoClientId = m_NetworkManager.ConnectionManager.TransportIdToClientId(sendTarget.ClientId);
|
||||||
mtu = NetworkManager.GetPeerMTU(ngoClientId);
|
mtu = m_NetworkManager.GetPeerMTU(ngoClientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
new SendBatchedMessagesJob
|
new SendBatchedMessagesJob
|
||||||
@@ -947,7 +975,7 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
|
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
|
||||||
if (NetworkManager)
|
if (m_NetworkManager)
|
||||||
{
|
{
|
||||||
ExtractNetworkMetrics();
|
ExtractNetworkMetrics();
|
||||||
}
|
}
|
||||||
@@ -963,16 +991,16 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
|
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
|
||||||
private void ExtractNetworkMetrics()
|
private void ExtractNetworkMetrics()
|
||||||
{
|
{
|
||||||
if (NetworkManager.IsServer)
|
if (m_NetworkManager.IsServer)
|
||||||
{
|
{
|
||||||
var ngoConnectionIds = NetworkManager.ConnectedClients.Keys;
|
var ngoConnectionIds = m_NetworkManager.ConnectedClients.Keys;
|
||||||
foreach (var ngoConnectionId in ngoConnectionIds)
|
foreach (var ngoConnectionId in ngoConnectionIds)
|
||||||
{
|
{
|
||||||
if (ngoConnectionId == 0 && NetworkManager.IsHost)
|
if (ngoConnectionId == 0 && m_NetworkManager.IsHost)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var transportClientId = NetworkManager.ConnectionManager.ClientIdToTransportId(ngoConnectionId);
|
var transportClientId = m_NetworkManager.ConnectionManager.ClientIdToTransportId(ngoConnectionId);
|
||||||
ExtractNetworkMetricsForClient(transportClientId);
|
ExtractNetworkMetricsForClient(transportClientId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -992,10 +1020,10 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
ExtractNetworkMetricsFromPipeline(m_UnreliableSequencedFragmentedPipeline, networkConnection);
|
ExtractNetworkMetricsFromPipeline(m_UnreliableSequencedFragmentedPipeline, networkConnection);
|
||||||
ExtractNetworkMetricsFromPipeline(m_ReliableSequencedPipeline, networkConnection);
|
ExtractNetworkMetricsFromPipeline(m_ReliableSequencedPipeline, networkConnection);
|
||||||
|
|
||||||
var rttValue = NetworkManager.IsServer ? 0 : ExtractRtt(networkConnection);
|
var rttValue = m_NetworkManager.IsServer ? 0 : ExtractRtt(networkConnection);
|
||||||
NetworkMetrics.UpdateRttToServer(rttValue);
|
NetworkMetrics.UpdateRttToServer(rttValue);
|
||||||
|
|
||||||
var packetLoss = NetworkManager.IsServer ? 0 : ExtractPacketLoss(networkConnection);
|
var packetLoss = m_NetworkManager.IsServer ? 0 : ExtractPacketLoss(networkConnection);
|
||||||
NetworkMetrics.UpdatePacketLoss(packetLoss);
|
NetworkMetrics.UpdatePacketLoss(packetLoss);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,9 +1227,9 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
// use the transport client ID) or from a user (which will be using the NGO client ID).
|
// use the transport client ID) or from a user (which will be using the NGO client ID).
|
||||||
// So we just try both cases (ExtractRtt returns 0 for invalid connections).
|
// So we just try both cases (ExtractRtt returns 0 for invalid connections).
|
||||||
|
|
||||||
if (NetworkManager != null)
|
if (m_NetworkManager != null)
|
||||||
{
|
{
|
||||||
var transportId = NetworkManager.ConnectionManager.ClientIdToTransportId(clientId);
|
var transportId = m_NetworkManager.ConnectionManager.ClientIdToTransportId(clientId);
|
||||||
|
|
||||||
var rtt = ExtractRtt(ParseClientId(transportId));
|
var rtt = ExtractRtt(ParseClientId(transportId));
|
||||||
if (rtt > 0)
|
if (rtt > 0)
|
||||||
@@ -1221,14 +1249,14 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
{
|
{
|
||||||
Debug.Assert(sizeof(ulong) == UnsafeUtility.SizeOf<NetworkConnection>(), "Netcode connection id size does not match UTP connection id size");
|
Debug.Assert(sizeof(ulong) == UnsafeUtility.SizeOf<NetworkConnection>(), "Netcode connection id size does not match UTP connection id size");
|
||||||
|
|
||||||
NetworkManager = networkManager;
|
m_NetworkManager = networkManager;
|
||||||
|
|
||||||
if (NetworkManager && NetworkManager.PortOverride.Overidden)
|
if (m_NetworkManager && m_NetworkManager.PortOverride.Overidden)
|
||||||
{
|
{
|
||||||
ConnectionData.Port = NetworkManager.PortOverride.Value;
|
ConnectionData.Port = m_NetworkManager.PortOverride.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_RealTimeProvider = NetworkManager ? NetworkManager.RealTimeProvider : new RealTimeProvider();
|
m_RealTimeProvider = m_NetworkManager ? m_NetworkManager.RealTimeProvider : new RealTimeProvider();
|
||||||
|
|
||||||
m_NetworkSettings = new NetworkSettings(Allocator.Persistent);
|
m_NetworkSettings = new NetworkSettings(Allocator.Persistent);
|
||||||
|
|
||||||
@@ -1322,7 +1350,7 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
// provide any reliability guarantees anymore. Disconnect the client since at
|
// provide any reliability guarantees anymore. Disconnect the client since at
|
||||||
// this point they're bound to become desynchronized.
|
// this point they're bound to become desynchronized.
|
||||||
|
|
||||||
var ngoClientId = NetworkManager?.ConnectionManager.TransportIdToClientId(clientId) ?? clientId;
|
var ngoClientId = m_NetworkManager?.ConnectionManager.TransportIdToClientId(clientId) ?? clientId;
|
||||||
Debug.LogError($"Couldn't add payload of size {payload.Count} to reliable send queue. " +
|
Debug.LogError($"Couldn't add payload of size {payload.Count} to reliable send queue. " +
|
||||||
$"Closing connection {ngoClientId} as reliability guarantees can't be maintained.");
|
$"Closing connection {ngoClientId} as reliability guarantees can't be maintained.");
|
||||||
|
|
||||||
@@ -1479,7 +1507,7 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
|
|
||||||
protected override NetworkTopologyTypes OnCurrentTopology()
|
protected override NetworkTopologyTypes OnCurrentTopology()
|
||||||
{
|
{
|
||||||
return NetworkManager != null ? NetworkManager.NetworkConfig.NetworkTopology : NetworkTopologyTypes.ClientServer;
|
return m_NetworkManager != null ? m_NetworkManager.NetworkConfig.NetworkTopology : NetworkTopologyTypes.ClientServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string m_ServerPrivateKey;
|
private string m_ServerPrivateKey;
|
||||||
@@ -1555,7 +1583,7 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
heartbeatTimeoutMS: transport.m_HeartbeatTimeoutMS);
|
heartbeatTimeoutMS: transport.m_HeartbeatTimeoutMS);
|
||||||
|
|
||||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||||
if (NetworkManager.IsServer && m_ProtocolType != ProtocolType.RelayUnityTransport)
|
if (m_NetworkManager.IsServer && m_ProtocolType != ProtocolType.RelayUnityTransport)
|
||||||
{
|
{
|
||||||
throw new Exception("WebGL as a server is not supported by Unity Transport, outside the Editor.");
|
throw new Exception("WebGL as a server is not supported by Unity Transport, outside the Editor.");
|
||||||
}
|
}
|
||||||
@@ -1577,7 +1605,7 @@ namespace Unity.Netcode.Transports.UTP
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (NetworkManager.IsServer)
|
if (m_NetworkManager.IsServer)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(m_ServerCertificate) || string.IsNullOrEmpty(m_ServerPrivateKey))
|
if (string.IsNullOrEmpty(m_ServerCertificate) || string.IsNullOrEmpty(m_ServerPrivateKey))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,11 @@
|
|||||||
"name": "com.unity.services.multiplayer",
|
"name": "com.unity.services.multiplayer",
|
||||||
"expression": "0.2.0",
|
"expression": "0.2.0",
|
||||||
"define": "MULTIPLAYER_SERVICES_SDK_INSTALLED"
|
"define": "MULTIPLAYER_SERVICES_SDK_INSTALLED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Unity",
|
||||||
|
"expression": "6000.0.11f1",
|
||||||
|
"define": "COM_UNITY_MODULES_PHYSICS2D_LINEAR"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|||||||
@@ -677,6 +677,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
foreach (var sceneToUnload in m_ScenesToUnload)
|
foreach (var sceneToUnload in m_ScenesToUnload)
|
||||||
{
|
{
|
||||||
SceneManager.UnloadSceneAsync(sceneToUnload.Key);
|
SceneManager.UnloadSceneAsync(sceneToUnload.Key);
|
||||||
|
// Update the ScenesLoaded when we unload scenes
|
||||||
|
if (sceneManager.ScenesLoaded.ContainsKey(sceneToUnload.Key.handle))
|
||||||
|
{
|
||||||
|
sceneManager.ScenesLoaded.Remove(sceneToUnload.Key.handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,8 +800,9 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
|
|
||||||
var sceneManager = networkManager.SceneManager;
|
var sceneManager = networkManager.SceneManager;
|
||||||
|
|
||||||
// Don't let client's set this value
|
// In client-server, we don't let client's set this value.
|
||||||
if (!networkManager.IsServer)
|
// In dsitributed authority, since session owner can be promoted clients can set this value
|
||||||
|
if (!networkManager.DistributedAuthorityMode && !networkManager.IsServer)
|
||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||||
{
|
{
|
||||||
@@ -804,7 +810,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode)
|
else if (!networkManager.DistributedAuthorityMode && networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode)
|
||||||
{
|
{
|
||||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -303,6 +303,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
OnOneTimeSetup();
|
OnOneTimeSetup();
|
||||||
|
|
||||||
VerboseDebug($"Exiting {nameof(OneTimeSetup)}");
|
VerboseDebug($"Exiting {nameof(OneTimeSetup)}");
|
||||||
|
|
||||||
|
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||||
|
// Default to not log the serialized type not optimized warning message when testing.
|
||||||
|
NetworkManager.DisableNotOptimizedSerializedType = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
/// Similar to WaitForClientConnected, this waits for multiple clients to be connected.
|
/// Similar to WaitForClientConnected, this waits for multiple clients to be connected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clients">The clients to be connected</param>
|
/// <param name="clients">The clients to be connected</param>
|
||||||
/// <param name="result">The result. If null, it will automatically assert<</param>
|
/// <param name="result">The result. If null, it will automatically assert</param>
|
||||||
/// <param name="maxFrames">The max frames to wait for</param>
|
/// <param name="maxFrames">The max frames to wait for</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, ResultWrapper<bool> result = null, float timeout = DefaultTimeout)
|
public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, ResultWrapper<bool> result = null, float timeout = DefaultTimeout)
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will automatically register for the NetworkVariable OnValueChanged
|
/// Will automatically register for the NetworkVariable OnValueChanged
|
||||||
/// delegate handler. It then will expose that single delegate invocation
|
/// delegate handler. It then will expose that single delegate invocation
|
||||||
/// to anything that registers for this NetworkVariableHelper's instance's OnValueChanged event.
|
/// to anything that registers for this NetworkVariableHelper's instance's OnValueChanged event.
|
||||||
/// This allows us to register any NetworkVariable type as well as there are basically two "types of types":
|
/// This allows us to register any NetworkVariable type as well as there are basically two "types of types":
|
||||||
/// IEquatable<T>
|
/// <list type="bullet">
|
||||||
/// ValueType
|
/// <item>IEquatable<T></item>
|
||||||
|
/// <item>ValueType</item>
|
||||||
|
/// </list>
|
||||||
/// From both we can then at least determine if the value indeed changed
|
/// From both we can then at least determine if the value indeed changed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
@@ -20,7 +22,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
|||||||
public event OnMyValueChangedDelegateHandler OnValueChanged;
|
public event OnMyValueChangedDelegateHandler OnValueChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IEquatable<T> Equals Check
|
/// IEquatable<T> Equals Check
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CheckVariableChanged(IEquatable<T> previous, IEquatable<T> next)
|
private void CheckVariableChanged(IEquatable<T> previous, IEquatable<T> next)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,11 +38,7 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
internal class TestNetworkComponent : NetworkBehaviour
|
internal class TestNetworkComponent : NetworkBehaviour
|
||||||
{
|
{
|
||||||
public NetworkList<int> MyNetworkList = new NetworkList<int>(new List<int> { 1, 2, 3 });
|
public NetworkList<int> MyNetworkList = new NetworkList<int>(new List<int> { 1, 2, 3 });
|
||||||
|
public NetworkVariable<int> MyNetworkVar = new NetworkVariable<int>(3);
|
||||||
[Rpc(SendTo.NotAuthority)]
|
|
||||||
public void TestNotAuthorityRpc(byte[] _)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Rpc(SendTo.Authority)]
|
[Rpc(SendTo.Authority)]
|
||||||
public void TestAuthorityRpc(byte[] _)
|
public void TestAuthorityRpc(byte[] _)
|
||||||
@@ -87,7 +83,7 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
Client.LogLevel = LogLevel.Developer;
|
Client.LogLevel = LogLevel.Developer;
|
||||||
|
|
||||||
// Validate we are in distributed authority mode with client side spawning and using CMB Service
|
// Validate we are in distributed authority mode with client side spawning and using CMB Service
|
||||||
Assert.True(Client.DistributedAuthorityMode, "Distributed authority is not set!");
|
Assert.True(Client.NetworkConfig.NetworkTopology == NetworkTopologyTypes.DistributedAuthority, "Distributed authority topology is not set!");
|
||||||
Assert.True(Client.AutoSpawnPlayerPrefabClientSide, "Client side spawning is not set!");
|
Assert.True(Client.AutoSpawnPlayerPrefabClientSide, "Client side spawning is not set!");
|
||||||
Assert.True(Client.CMBServiceConnection, "CMBServiceConnection is not set!");
|
Assert.True(Client.CMBServiceConnection, "CMBServiceConnection is not set!");
|
||||||
|
|
||||||
@@ -101,6 +97,9 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
|
|
||||||
protected override IEnumerator OnStartedServerAndClients()
|
protected override IEnumerator OnStartedServerAndClients()
|
||||||
{
|
{
|
||||||
|
// Validate the NetworkManager are in distributed authority mode
|
||||||
|
Assert.True(Client.DistributedAuthorityMode, "Distributed authority is not set!");
|
||||||
|
|
||||||
// Register hooks after starting clients and server (in this case just the one client)
|
// Register hooks after starting clients and server (in this case just the one client)
|
||||||
// We do this at this point in time because the MessageManager exists (happens within the same call stack when starting NetworkManagers)
|
// We do this at this point in time because the MessageManager exists (happens within the same call stack when starting NetworkManagers)
|
||||||
m_ClientCodecHook = new CodecTestHooks();
|
m_ClientCodecHook = new CodecTestHooks();
|
||||||
@@ -219,12 +218,44 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator NotAuthorityRpc()
|
public IEnumerator NetworkVariableDelta_WithValueUpdate()
|
||||||
{
|
{
|
||||||
Client.LocalClient.PlayerObject.GetComponent<TestNetworkComponent>().TestNotAuthorityRpc(new byte[] { 1, 2, 3, 4 });
|
var networkObj = CreateNetworkObjectPrefab("TestObject");
|
||||||
|
networkObj.AddComponent<TestNetworkComponent>();
|
||||||
|
var instance = SpawnObject(networkObj, Client);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<CreateObjectMessage>();
|
||||||
|
var component = instance.GetComponent<TestNetworkComponent>();
|
||||||
|
|
||||||
// Universal Rpcs are sent as a ProxyMessage (which contains an RpcMessage)
|
var newValue = 5;
|
||||||
yield return m_ClientCodecHook.WaitForMessageReceived<ProxyMessage>();
|
component.MyNetworkVar.Value = newValue;
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
Assert.AreEqual(newValue, component.MyNetworkVar.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator NetworkListDelta_WithValueUpdate()
|
||||||
|
{
|
||||||
|
var networkObj = CreateNetworkObjectPrefab("TestObject");
|
||||||
|
networkObj.AddComponent<TestNetworkComponent>();
|
||||||
|
var instance = SpawnObject(networkObj, Client);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<CreateObjectMessage>();
|
||||||
|
var component = instance.GetComponent<TestNetworkComponent>();
|
||||||
|
|
||||||
|
component.MyNetworkList.Add(5);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.Add(6);
|
||||||
|
component.MyNetworkList.Add(7);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.Insert(1, 8);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.Insert(8, 11);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.Remove(6);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.RemoveAt(2);
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
|
component.MyNetworkList.Clear();
|
||||||
|
yield return m_ClientCodecHook.WaitForMessageReceived<NetworkVariableDeltaMessage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
|
|||||||
97
Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs
Normal file
97
Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Unity.Netcode.TestHelpers.Runtime;
|
||||||
|
|
||||||
|
namespace Unity.Netcode.RuntimeTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This test validates PR-3000 where it would invoke
|
||||||
|
/// TODO:
|
||||||
|
/// We really need to get the service running during tests
|
||||||
|
/// so we can validate these issues. While this test does
|
||||||
|
/// partially validate it we still need to manually validate
|
||||||
|
/// with a service connection.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture(HostOrServer.Host)]
|
||||||
|
[TestFixture(HostOrServer.DAHost)]
|
||||||
|
public class RpcProxyMessageTesting : NetcodeIntegrationTest
|
||||||
|
{
|
||||||
|
protected override int NumberOfClients => 2;
|
||||||
|
|
||||||
|
private List<RpcProxyText> m_ProxyTestInstances = new List<RpcProxyText>();
|
||||||
|
|
||||||
|
private StringBuilder m_ValidationLogger = new StringBuilder();
|
||||||
|
|
||||||
|
public RpcProxyMessageTesting(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||||
|
|
||||||
|
protected override IEnumerator OnSetup()
|
||||||
|
{
|
||||||
|
m_ProxyTestInstances.Clear();
|
||||||
|
return base.OnSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnCreatePlayerPrefab()
|
||||||
|
{
|
||||||
|
m_PlayerPrefab.AddComponent<RpcProxyText>();
|
||||||
|
base.OnCreatePlayerPrefab();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool ValidateRpcProxyRpcs()
|
||||||
|
{
|
||||||
|
m_ValidationLogger.Clear();
|
||||||
|
foreach (var proxy in m_ProxyTestInstances)
|
||||||
|
{
|
||||||
|
if (proxy.ReceivedRpc.Count < NumberOfClients)
|
||||||
|
{
|
||||||
|
m_ValidationLogger.AppendLine($"Not all clients received RPC from Client-{proxy.OwnerClientId}!");
|
||||||
|
}
|
||||||
|
foreach (var clientId in proxy.ReceivedRpc)
|
||||||
|
{
|
||||||
|
if (clientId == proxy.OwnerClientId)
|
||||||
|
{
|
||||||
|
m_ValidationLogger.AppendLine($"Client-{proxy.OwnerClientId} sent itself an Rpc!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_ValidationLogger.Length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerator ProxyDoesNotInvokeOnSender()
|
||||||
|
{
|
||||||
|
m_ProxyTestInstances.Add(m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent<RpcProxyText>());
|
||||||
|
foreach (var client in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
m_ProxyTestInstances.Add(client.LocalClient.PlayerObject.GetComponent<RpcProxyText>());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var clientProxyTest in m_ProxyTestInstances)
|
||||||
|
{
|
||||||
|
clientProxyTest.SendToEveryOneButMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return WaitForConditionOrTimeOut(ValidateRpcProxyRpcs);
|
||||||
|
AssertOnTimeout(m_ValidationLogger.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RpcProxyText : NetworkBehaviour
|
||||||
|
{
|
||||||
|
public List<ulong> ReceivedRpc = new List<ulong>();
|
||||||
|
|
||||||
|
public void SendToEveryOneButMe()
|
||||||
|
{
|
||||||
|
var baseTarget = NetworkManager.DistributedAuthorityMode ? RpcTarget.NotAuthority : RpcTarget.NotMe;
|
||||||
|
TestRpc(baseTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Rpc(SendTo.SpecifiedInParams)]
|
||||||
|
private void TestRpc(RpcParams rpcParams = default)
|
||||||
|
{
|
||||||
|
ReceivedRpc.Add(rpcParams.Receive.SenderClientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 22d1d751fe245f7419f8393090c27106
|
||||||
8
Tests/Runtime/NetworkVariable.meta
Normal file
8
Tests/Runtime/NetworkVariable.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7b4da27c6efa9684893f85f5d3ad80e6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
2994
Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs
Normal file
2994
Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7d01969a8bbbd7146a24490a5190ea7e
|
||||||
165
Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs
Normal file
165
Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#if !NGO_MINIMALPROJECT
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Unity.Netcode.TestHelpers.Runtime;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace Unity.Netcode.RuntimeTests
|
||||||
|
{
|
||||||
|
[TestFixtureSource(nameof(TestDataSource))]
|
||||||
|
internal class NetworkVariableInheritanceTests : NetcodeIntegrationTest
|
||||||
|
{
|
||||||
|
public NetworkVariableInheritanceTests(HostOrServer hostOrServer)
|
||||||
|
: base(hostOrServer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int NumberOfClients => 2;
|
||||||
|
|
||||||
|
public static IEnumerable<TestFixtureData> TestDataSource() =>
|
||||||
|
Enum.GetValues(typeof(HostOrServer)).OfType<HostOrServer>().Select(x => new TestFixtureData(x));
|
||||||
|
|
||||||
|
internal class ComponentA : NetworkBehaviour
|
||||||
|
{
|
||||||
|
public NetworkVariable<int> PublicFieldA = new NetworkVariable<int>(1);
|
||||||
|
protected NetworkVariable<int> m_ProtectedFieldA = new NetworkVariable<int>(2);
|
||||||
|
private NetworkVariable<int> m_PrivateFieldA = new NetworkVariable<int>(3);
|
||||||
|
|
||||||
|
public void ChangeValuesA(int pub, int pro, int pri)
|
||||||
|
{
|
||||||
|
PublicFieldA.Value = pub;
|
||||||
|
m_ProtectedFieldA.Value = pro;
|
||||||
|
m_PrivateFieldA.Value = pri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CompareValuesA(ComponentA other)
|
||||||
|
{
|
||||||
|
return PublicFieldA.Value == other.PublicFieldA.Value &&
|
||||||
|
m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value &&
|
||||||
|
m_PrivateFieldA.Value == other.m_PrivateFieldA.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ComponentB : ComponentA
|
||||||
|
{
|
||||||
|
public NetworkVariable<int> PublicFieldB = new NetworkVariable<int>(11);
|
||||||
|
protected NetworkVariable<int> m_ProtectedFieldB = new NetworkVariable<int>(22);
|
||||||
|
private NetworkVariable<int> m_PrivateFieldB = new NetworkVariable<int>(33);
|
||||||
|
|
||||||
|
public void ChangeValuesB(int pub, int pro, int pri)
|
||||||
|
{
|
||||||
|
PublicFieldB.Value = pub;
|
||||||
|
m_ProtectedFieldB.Value = pro;
|
||||||
|
m_PrivateFieldB.Value = pri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CompareValuesB(ComponentB other)
|
||||||
|
{
|
||||||
|
return PublicFieldB.Value == other.PublicFieldB.Value &&
|
||||||
|
m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value &&
|
||||||
|
m_PrivateFieldB.Value == other.m_PrivateFieldB.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ComponentC : ComponentB
|
||||||
|
{
|
||||||
|
public NetworkVariable<int> PublicFieldC = new NetworkVariable<int>(111);
|
||||||
|
protected NetworkVariable<int> m_ProtectedFieldC = new NetworkVariable<int>(222);
|
||||||
|
private NetworkVariable<int> m_PrivateFieldC = new NetworkVariable<int>(333);
|
||||||
|
|
||||||
|
public void ChangeValuesC(int pub, int pro, int pri)
|
||||||
|
{
|
||||||
|
PublicFieldC.Value = pub;
|
||||||
|
m_ProtectedFieldA.Value = pro;
|
||||||
|
m_PrivateFieldC.Value = pri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CompareValuesC(ComponentC other)
|
||||||
|
{
|
||||||
|
return PublicFieldC.Value == other.PublicFieldC.Value &&
|
||||||
|
m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value &&
|
||||||
|
m_PrivateFieldC.Value == other.m_PrivateFieldC.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameObject m_TestObjectPrefab;
|
||||||
|
private ulong m_TestObjectId = 0;
|
||||||
|
|
||||||
|
protected override void OnOneTimeSetup()
|
||||||
|
{
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = true;
|
||||||
|
base.OnOneTimeSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnOneTimeTearDown()
|
||||||
|
{
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = false;
|
||||||
|
base.OnOneTimeTearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnServerAndClientsCreated()
|
||||||
|
{
|
||||||
|
m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]");
|
||||||
|
m_TestObjectPrefab.AddComponent<ComponentA>();
|
||||||
|
m_TestObjectPrefab.AddComponent<ComponentB>();
|
||||||
|
m_TestObjectPrefab.AddComponent<ComponentC>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerator OnServerAndClientsConnected()
|
||||||
|
{
|
||||||
|
var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>();
|
||||||
|
m_TestObjectId = serverTestObject.NetworkObjectId;
|
||||||
|
|
||||||
|
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
||||||
|
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
||||||
|
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
||||||
|
|
||||||
|
serverTestComponentA.ChangeValuesA(1000, 2000, 3000);
|
||||||
|
serverTestComponentB.ChangeValuesA(1000, 2000, 3000);
|
||||||
|
serverTestComponentB.ChangeValuesB(1100, 2200, 3300);
|
||||||
|
serverTestComponentC.ChangeValuesA(1000, 2000, 3000);
|
||||||
|
serverTestComponentC.ChangeValuesB(1100, 2200, 3300);
|
||||||
|
serverTestComponentC.ChangeValuesC(1110, 2220, 3330);
|
||||||
|
|
||||||
|
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckTestObjectComponentValuesOnAll()
|
||||||
|
{
|
||||||
|
var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
||||||
|
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
||||||
|
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
||||||
|
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
||||||
|
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
||||||
|
var clientTestComponentA = clientTestObject.GetComponent<ComponentA>();
|
||||||
|
var clientTestComponentB = clientTestObject.GetComponent<ComponentB>();
|
||||||
|
var clientTestComponentC = clientTestObject.GetComponent<ComponentC>();
|
||||||
|
if (!serverTestComponentA.CompareValuesA(clientTestComponentA) ||
|
||||||
|
!serverTestComponentB.CompareValuesA(clientTestComponentB) ||
|
||||||
|
!serverTestComponentB.CompareValuesB(clientTestComponentB) ||
|
||||||
|
!serverTestComponentC.CompareValuesA(clientTestComponentC) ||
|
||||||
|
!serverTestComponentC.CompareValuesB(clientTestComponentC) ||
|
||||||
|
!serverTestComponentC.CompareValuesC(clientTestComponentC))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TestInheritedFields()
|
||||||
|
{
|
||||||
|
yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll);
|
||||||
|
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 41d4aef8f33a8eb4e87879075f868e66
|
||||||
306
Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs
Normal file
306
Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
#if !NGO_MINIMALPROJECT
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Unity.Netcode.TestHelpers.Runtime;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
|
namespace Unity.Netcode.RuntimeTests
|
||||||
|
{
|
||||||
|
[TestFixtureSource(nameof(TestDataSource))]
|
||||||
|
internal class NetworkVariablePermissionTests : NetcodeIntegrationTest
|
||||||
|
{
|
||||||
|
public static IEnumerable<TestFixtureData> TestDataSource()
|
||||||
|
{
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = true;
|
||||||
|
foreach (HostOrServer hostOrServer in Enum.GetValues(typeof(HostOrServer)))
|
||||||
|
{
|
||||||
|
// DANGO-EXP TODO: Add support for distributed authority mode
|
||||||
|
if (hostOrServer == HostOrServer.DAHost)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return new TestFixtureData(hostOrServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int NumberOfClients => 3;
|
||||||
|
|
||||||
|
public NetworkVariablePermissionTests(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||||
|
|
||||||
|
private GameObject m_TestObjPrefab;
|
||||||
|
private ulong m_TestObjId = 0;
|
||||||
|
|
||||||
|
protected override void OnServerAndClientsCreated()
|
||||||
|
{
|
||||||
|
m_TestObjPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariablePermissionTests)}.{nameof(m_TestObjPrefab)}]");
|
||||||
|
var testComp = m_TestObjPrefab.AddComponent<NetVarPermTestComp>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerator OnServerAndClientsConnected()
|
||||||
|
{
|
||||||
|
m_TestObjId = SpawnObject(m_TestObjPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>().NetworkObjectId;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator WaitForPositionsAreEqual(NetworkVariable<Vector3> netvar, Vector3 expected)
|
||||||
|
{
|
||||||
|
yield return WaitForConditionOrTimeOut(() => netvar.Value == expected);
|
||||||
|
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator WaitForOwnerWritableAreEqualOnAll()
|
||||||
|
{
|
||||||
|
yield return WaitForConditionOrTimeOut(CheckOwnerWritableAreEqualOnAll);
|
||||||
|
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckOwnerWritableAreEqualOnAll()
|
||||||
|
{
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
if (testObjServer.OwnerClientId != testObjClient.OwnerClientId ||
|
||||||
|
testCompServer.OwnerWritable_Position.Value != testCompClient.OwnerWritable_Position.Value ||
|
||||||
|
testCompServer.OwnerWritable_Position.ReadPerm != testCompClient.OwnerWritable_Position.ReadPerm ||
|
||||||
|
testCompServer.OwnerWritable_Position.WritePerm != testCompClient.OwnerWritable_Position.WritePerm)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator WaitForServerWritableAreEqualOnAll()
|
||||||
|
{
|
||||||
|
yield return WaitForConditionOrTimeOut(CheckServerWritableAreEqualOnAll);
|
||||||
|
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckServerWritableAreEqualOnAll()
|
||||||
|
{
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
if (testCompServer.ServerWritable_Position.Value != testCompClient.ServerWritable_Position.Value ||
|
||||||
|
testCompServer.ServerWritable_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
||||||
|
testCompServer.ServerWritable_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckOwnerReadWriteAreEqualOnOwnerAndServer()
|
||||||
|
{
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
if (testObjServer.OwnerClientId == testObjClient.OwnerClientId &&
|
||||||
|
testCompServer.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value &&
|
||||||
|
testCompServer.OwnerReadWrite_Position.ReadPerm == testCompClient.ServerWritable_Position.ReadPerm &&
|
||||||
|
testCompServer.OwnerReadWrite_Position.WritePerm == testCompClient.ServerWritable_Position.WritePerm)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(NetVarPermTestComp ownerReadWriteObject)
|
||||||
|
{
|
||||||
|
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||||
|
{
|
||||||
|
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
if (testObjClient.OwnerClientId != ownerReadWriteObject.OwnerClientId ||
|
||||||
|
ownerReadWriteObject.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value ||
|
||||||
|
ownerReadWriteObject.OwnerReadWrite_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
||||||
|
ownerReadWriteObject.OwnerReadWrite_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ServerChangesOwnerWritableNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
|
||||||
|
testCompServer.OwnerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, newValue);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ServerChangesServerWritableNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
var oldValue = testCompServer.ServerWritable_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
|
||||||
|
testCompServer.ServerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
||||||
|
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ClientChangesOwnerWritableNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
|
||||||
|
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||||
|
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||||
|
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||||
|
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
var oldValue = testCompClient.OwnerWritable_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
|
||||||
|
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This tests the scenario where a client owner has both read and write
|
||||||
|
/// permissions set. The server should be the only instance that can read
|
||||||
|
/// the NetworkVariable. ServerCannotChangeOwnerWritableNetVar performs
|
||||||
|
/// the same check to make sure the server cannot write to a client owner
|
||||||
|
/// NetworkVariable with owner write permissions.
|
||||||
|
/// </summary>
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ClientOwnerWithReadWriteChangesNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
|
||||||
|
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||||
|
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||||
|
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||||
|
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
var oldValue = testCompClient.OwnerReadWrite_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
|
||||||
|
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||||
|
|
||||||
|
// Verify the client owner and server match
|
||||||
|
yield return CheckOwnerReadWriteAreEqualOnOwnerAndServer();
|
||||||
|
|
||||||
|
// Verify the non-owner clients do not have the same Value but do have the same permissions
|
||||||
|
yield return CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(testCompClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ClientCannotChangeServerWritableNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||||
|
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||||
|
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||||
|
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||||
|
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
var oldValue = testCompClient.ServerWritable_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
LogAssert.Expect(LogType.Error, testCompClient.ServerWritable_Position.GetWritePermissionError());
|
||||||
|
testCompClient.ServerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, oldValue);
|
||||||
|
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
testCompServer.ServerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
||||||
|
|
||||||
|
yield return WaitForServerWritableAreEqualOnAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ServerCannotChangeOwnerWritableNetVar()
|
||||||
|
{
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||||
|
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||||
|
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||||
|
yield return WaitForTicks(m_ServerNetworkManager, 4);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
||||||
|
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||||
|
|
||||||
|
LogAssert.Expect(LogType.Error, testCompServer.OwnerWritable_Position.GetWritePermissionError());
|
||||||
|
testCompServer.OwnerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, oldValue);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
|
||||||
|
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||||
|
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||||
|
|
||||||
|
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||||
|
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||||
|
|
||||||
|
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 60d49d322bef8ff4ebb8c4abf57e18e3
|
||||||
@@ -12,298 +12,6 @@ using Random = UnityEngine.Random;
|
|||||||
|
|
||||||
namespace Unity.Netcode.RuntimeTests
|
namespace Unity.Netcode.RuntimeTests
|
||||||
{
|
{
|
||||||
[TestFixtureSource(nameof(TestDataSource))]
|
|
||||||
internal class NetworkVariablePermissionTests : NetcodeIntegrationTest
|
|
||||||
{
|
|
||||||
public static IEnumerable<TestFixtureData> TestDataSource()
|
|
||||||
{
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = true;
|
|
||||||
foreach (HostOrServer hostOrServer in Enum.GetValues(typeof(HostOrServer)))
|
|
||||||
{
|
|
||||||
// DANGO-EXP TODO: Add support for distributed authority mode
|
|
||||||
if (hostOrServer == HostOrServer.DAHost)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
yield return new TestFixtureData(hostOrServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int NumberOfClients => 3;
|
|
||||||
|
|
||||||
public NetworkVariablePermissionTests(HostOrServer hostOrServer) : base(hostOrServer) { }
|
|
||||||
|
|
||||||
private GameObject m_TestObjPrefab;
|
|
||||||
private ulong m_TestObjId = 0;
|
|
||||||
|
|
||||||
protected override void OnServerAndClientsCreated()
|
|
||||||
{
|
|
||||||
m_TestObjPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariablePermissionTests)}.{nameof(m_TestObjPrefab)}]");
|
|
||||||
var testComp = m_TestObjPrefab.AddComponent<NetVarPermTestComp>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerator OnServerAndClientsConnected()
|
|
||||||
{
|
|
||||||
m_TestObjId = SpawnObject(m_TestObjPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>().NetworkObjectId;
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerator WaitForPositionsAreEqual(NetworkVariable<Vector3> netvar, Vector3 expected)
|
|
||||||
{
|
|
||||||
yield return WaitForConditionOrTimeOut(() => netvar.Value == expected);
|
|
||||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerator WaitForOwnerWritableAreEqualOnAll()
|
|
||||||
{
|
|
||||||
yield return WaitForConditionOrTimeOut(CheckOwnerWritableAreEqualOnAll);
|
|
||||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckOwnerWritableAreEqualOnAll()
|
|
||||||
{
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
|
||||||
{
|
|
||||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
if (testObjServer.OwnerClientId != testObjClient.OwnerClientId ||
|
|
||||||
testCompServer.OwnerWritable_Position.Value != testCompClient.OwnerWritable_Position.Value ||
|
|
||||||
testCompServer.OwnerWritable_Position.ReadPerm != testCompClient.OwnerWritable_Position.ReadPerm ||
|
|
||||||
testCompServer.OwnerWritable_Position.WritePerm != testCompClient.OwnerWritable_Position.WritePerm)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerator WaitForServerWritableAreEqualOnAll()
|
|
||||||
{
|
|
||||||
yield return WaitForConditionOrTimeOut(CheckServerWritableAreEqualOnAll);
|
|
||||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckServerWritableAreEqualOnAll()
|
|
||||||
{
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
|
||||||
{
|
|
||||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
if (testCompServer.ServerWritable_Position.Value != testCompClient.ServerWritable_Position.Value ||
|
|
||||||
testCompServer.ServerWritable_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
|
||||||
testCompServer.ServerWritable_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckOwnerReadWriteAreEqualOnOwnerAndServer()
|
|
||||||
{
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
|
||||||
{
|
|
||||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
if (testObjServer.OwnerClientId == testObjClient.OwnerClientId &&
|
|
||||||
testCompServer.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value &&
|
|
||||||
testCompServer.OwnerReadWrite_Position.ReadPerm == testCompClient.ServerWritable_Position.ReadPerm &&
|
|
||||||
testCompServer.OwnerReadWrite_Position.WritePerm == testCompClient.ServerWritable_Position.WritePerm)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(NetVarPermTestComp ownerReadWriteObject)
|
|
||||||
{
|
|
||||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
|
||||||
{
|
|
||||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
if (testObjClient.OwnerClientId != ownerReadWriteObject.OwnerClientId ||
|
|
||||||
ownerReadWriteObject.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value ||
|
|
||||||
ownerReadWriteObject.OwnerReadWrite_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
|
||||||
ownerReadWriteObject.OwnerReadWrite_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ServerChangesOwnerWritableNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
testCompServer.OwnerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, newValue);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ServerChangesServerWritableNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
var oldValue = testCompServer.ServerWritable_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
testCompServer.ServerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
|
||||||
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ClientChangesOwnerWritableNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
|
|
||||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
|
||||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
|
||||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
var oldValue = testCompClient.OwnerWritable_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This tests the scenario where a client owner has both read and write
|
|
||||||
/// permissions set. The server should be the only instance that can read
|
|
||||||
/// the NetworkVariable. ServerCannotChangeOwnerWritableNetVar performs
|
|
||||||
/// the same check to make sure the server cannot write to a client owner
|
|
||||||
/// NetworkVariable with owner write permissions.
|
|
||||||
/// </summary>
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ClientOwnerWithReadWriteChangesNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
|
|
||||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
|
||||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
|
||||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
var oldValue = testCompClient.OwnerReadWrite_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
|
||||||
|
|
||||||
// Verify the client owner and server match
|
|
||||||
yield return CheckOwnerReadWriteAreEqualOnOwnerAndServer();
|
|
||||||
|
|
||||||
// Verify the non-owner clients do not have the same Value but do have the same permissions
|
|
||||||
yield return CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(testCompClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ClientCannotChangeServerWritableNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
|
||||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
|
||||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
|
||||||
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
var oldValue = testCompClient.ServerWritable_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
Assert.That(() => testCompClient.ServerWritable_Position.Value = newValue, Throws.TypeOf<InvalidOperationException>());
|
|
||||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, oldValue);
|
|
||||||
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
testCompServer.ServerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
|
||||||
|
|
||||||
yield return WaitForServerWritableAreEqualOnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ServerCannotChangeOwnerWritableNetVar()
|
|
||||||
{
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
|
||||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
|
||||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
|
||||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
|
||||||
|
|
||||||
Assert.That(() => testCompServer.OwnerWritable_Position.Value = newValue, Throws.TypeOf<InvalidOperationException>());
|
|
||||||
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, oldValue);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
|
|
||||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
|
||||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
|
||||||
|
|
||||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
|
||||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
|
||||||
|
|
||||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal struct TestStruct : INetworkSerializable, IEquatable<TestStruct>
|
internal struct TestStruct : INetworkSerializable, IEquatable<TestStruct>
|
||||||
{
|
{
|
||||||
public uint SomeInt;
|
public uint SomeInt;
|
||||||
@@ -438,6 +146,255 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the more generic conditional logic for NetworkList tests
|
||||||
|
/// which can be used with the <see cref="NetcodeIntegrationTest.WaitForConditionOrTimeOut"/>
|
||||||
|
/// that accepts anything derived from the <see cref="ConditionalPredicateBase"/> class
|
||||||
|
/// as a parameter.
|
||||||
|
/// </summary>
|
||||||
|
internal class NetworkListTestPredicate : ConditionalPredicateBase
|
||||||
|
{
|
||||||
|
private const int k_MaxRandomValue = 1000;
|
||||||
|
|
||||||
|
private Dictionary<NetworkListTestStates, Func<bool>> m_StateFunctions;
|
||||||
|
|
||||||
|
// Player1 component on the Server
|
||||||
|
private NetworkVariableTest m_Player1OnServer;
|
||||||
|
|
||||||
|
// Player1 component on client1
|
||||||
|
private NetworkVariableTest m_Player1OnClient1;
|
||||||
|
|
||||||
|
private string m_TestStageFailedMessage;
|
||||||
|
|
||||||
|
public enum NetworkListTestStates
|
||||||
|
{
|
||||||
|
Add,
|
||||||
|
ContainsLarge,
|
||||||
|
Contains,
|
||||||
|
VerifyData,
|
||||||
|
IndexOf,
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkListTestStates m_NetworkListTestState;
|
||||||
|
|
||||||
|
public void SetNetworkListTestState(NetworkListTestStates networkListTestState)
|
||||||
|
{
|
||||||
|
m_NetworkListTestState = networkListTestState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the condition has been reached for the current NetworkListTestState
|
||||||
|
/// </summary>
|
||||||
|
protected override bool OnHasConditionBeenReached()
|
||||||
|
{
|
||||||
|
var isStateRegistered = m_StateFunctions.ContainsKey(m_NetworkListTestState);
|
||||||
|
Assert.IsTrue(isStateRegistered);
|
||||||
|
return m_StateFunctions[m_NetworkListTestState].Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides all information about the players for both sides for simplicity and informative sake.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string ConditionFailedInfo()
|
||||||
|
{
|
||||||
|
return $"{m_NetworkListTestState} condition test failed:\n Server List Count: {m_Player1OnServer.TheList.Count} vs Client List Count: {m_Player1OnClient1.TheList.Count}\n" +
|
||||||
|
$"Server List Count: {m_Player1OnServer.TheLargeList.Count} vs Client List Count: {m_Player1OnClient1.TheLargeList.Count}\n" +
|
||||||
|
$"Server Delegate Triggered: {m_Player1OnServer.ListDelegateTriggered} | Client Delegate Triggered: {m_Player1OnClient1.ListDelegateTriggered}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When finished, check if a time out occurred and if so assert and provide meaningful information to troubleshoot why
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnFinished()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(TimedOut, $"{nameof(NetworkListTestPredicate)} timed out waiting for the {m_NetworkListTestState} condition to be reached! \n" + ConditionFailedInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses the ArrayOperator and validates that on both sides the count and values are the same
|
||||||
|
private bool OnVerifyData()
|
||||||
|
{
|
||||||
|
// Wait until both sides have the same number of elements
|
||||||
|
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the client values against the server values to make sure they match
|
||||||
|
for (int i = 0; i < m_Player1OnServer.TheList.Count; i++)
|
||||||
|
{
|
||||||
|
if (m_Player1OnServer.TheList[i] != m_Player1OnClient1.TheList[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies the data count, values, and that the ListDelegate on both sides was triggered
|
||||||
|
/// </summary>
|
||||||
|
private bool OnAdd()
|
||||||
|
{
|
||||||
|
bool wasTriggerred = m_Player1OnServer.ListDelegateTriggered && m_Player1OnClient1.ListDelegateTriggered;
|
||||||
|
return wasTriggerred && OnVerifyData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current version of this test only verified the count of the large list, so that is what this does
|
||||||
|
/// </summary>
|
||||||
|
private bool OnContainsLarge()
|
||||||
|
{
|
||||||
|
return m_Player1OnServer.TheLargeList.Count == m_Player1OnClient1.TheLargeList.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests NetworkList.Contains which also verifies all values are the same on both sides
|
||||||
|
/// </summary>
|
||||||
|
private bool OnContains()
|
||||||
|
{
|
||||||
|
// Wait until both sides have the same number of elements
|
||||||
|
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse through all server values and use the NetworkList.Contains method to check if the value is in the list on the client side
|
||||||
|
foreach (var serverValue in m_Player1OnServer.TheList)
|
||||||
|
{
|
||||||
|
if (!m_Player1OnClient1.TheList.Contains(serverValue))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests NetworkList.IndexOf and verifies that all values are aligned on both sides
|
||||||
|
/// </summary>
|
||||||
|
private bool OnIndexOf()
|
||||||
|
{
|
||||||
|
foreach (var serverSideValue in m_Player1OnServer.TheList)
|
||||||
|
{
|
||||||
|
var indexToTest = m_Player1OnServer.TheList.IndexOf(serverSideValue);
|
||||||
|
if (indexToTest != m_Player1OnServer.TheList.IndexOf(serverSideValue))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVariableTest player1OnClient1, NetworkListTestStates networkListTestState, int elementCount)
|
||||||
|
{
|
||||||
|
m_NetworkListTestState = networkListTestState;
|
||||||
|
m_Player1OnServer = player1OnServer;
|
||||||
|
m_Player1OnClient1 = player1OnClient1;
|
||||||
|
m_StateFunctions = new Dictionary<NetworkListTestStates, Func<bool>>
|
||||||
|
{
|
||||||
|
{ NetworkListTestStates.Add, OnAdd },
|
||||||
|
{ NetworkListTestStates.ContainsLarge, OnContainsLarge },
|
||||||
|
{ NetworkListTestStates.Contains, OnContains },
|
||||||
|
{ NetworkListTestStates.VerifyData, OnVerifyData },
|
||||||
|
{ NetworkListTestStates.IndexOf, OnIndexOf }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (networkListTestState == NetworkListTestStates.ContainsLarge)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < elementCount; ++i)
|
||||||
|
{
|
||||||
|
m_Player1OnServer.TheLargeList.Add(new FixedString128Bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < elementCount; i++)
|
||||||
|
{
|
||||||
|
m_Player1OnServer.TheList.Add(Random.Range(0, k_MaxRandomValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NetvarDespawnShutdown : NetworkBehaviour
|
||||||
|
{
|
||||||
|
private NetworkVariable<int> m_IntNetworkVariable = new NetworkVariable<int>();
|
||||||
|
private NetworkList<int> m_IntList;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
m_IntList = new NetworkList<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNetworkDespawn()
|
||||||
|
{
|
||||||
|
if (IsServer)
|
||||||
|
{
|
||||||
|
m_IntNetworkVariable.Value = 5;
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
m_IntList.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnNetworkDespawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates that setting values for NetworkVariable or NetworkList during the
|
||||||
|
/// OnNetworkDespawn method will not cause an exception to occur.
|
||||||
|
/// </summary>
|
||||||
|
internal class NetworkVariableModifyOnNetworkDespawn : NetcodeIntegrationTest
|
||||||
|
{
|
||||||
|
protected override int NumberOfClients => 1;
|
||||||
|
|
||||||
|
private GameObject m_TestPrefab;
|
||||||
|
|
||||||
|
protected override void OnOneTimeSetup()
|
||||||
|
{
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = true;
|
||||||
|
base.OnOneTimeSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnOneTimeTearDown()
|
||||||
|
{
|
||||||
|
NetworkVariableBase.IgnoreInitializeWarning = false;
|
||||||
|
base.OnOneTimeTearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnServerAndClientsCreated()
|
||||||
|
{
|
||||||
|
m_TestPrefab = CreateNetworkObjectPrefab("NetVarDespawn");
|
||||||
|
m_TestPrefab.AddComponent<NetvarDespawnShutdown>();
|
||||||
|
base.OnServerAndClientsCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnClientSpawnedTestPrefab(ulong networkObjectId)
|
||||||
|
{
|
||||||
|
var clientId = m_ClientNetworkManagers[0].LocalClientId;
|
||||||
|
if (!s_GlobalNetworkObjects.ContainsKey(clientId))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_GlobalNetworkObjects[clientId].ContainsKey(networkObjectId))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ModifyNetworkVariableOrListOnNetworkDespawn()
|
||||||
|
{
|
||||||
|
var instance = SpawnObject(m_TestPrefab, m_ServerNetworkManager);
|
||||||
|
yield return WaitForConditionOrTimeOut(() => OnClientSpawnedTestPrefab(instance.GetComponent<NetworkObject>().NetworkObjectId));
|
||||||
|
m_ServerNetworkManager.Shutdown();
|
||||||
|
// As long as no excetptions occur, the test passes.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !MULTIPLAYER_TOOLS
|
#if !MULTIPLAYER_TOOLS
|
||||||
[TestFixture(true)]
|
[TestFixture(true)]
|
||||||
@@ -612,7 +569,9 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
InitializeServerAndClients(useHost);
|
InitializeServerAndClients(useHost);
|
||||||
|
|
||||||
// client must not be allowed to write to a server auth variable
|
// client must not be allowed to write to a server auth variable
|
||||||
Assert.Throws<InvalidOperationException>(() => m_Player1OnClient1.TheScalar.Value = k_TestVal1);
|
|
||||||
|
LogAssert.Expect(LogType.Error, m_Player1OnClient1.TheScalar.GetWritePermissionError());
|
||||||
|
m_Player1OnClient1.TheScalar.Value = k_TestVal1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1053,7 +1012,8 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestUnsupportedManagedTypesWithUserSerializationDoNotThrowExceptions()
|
// Exceptions should be thrown in DA mode with UserNetworkVariableSerialization
|
||||||
|
public void TestUnsupportedManagedTypesWithUserSerializationDoNotThrowExceptionsInClientServerMode()
|
||||||
{
|
{
|
||||||
var variable = new NetworkVariable<string>();
|
var variable = new NetworkVariable<string>();
|
||||||
UserNetworkVariableSerialization<string>.ReadValue = (FastBufferReader reader, out string value) =>
|
UserNetworkVariableSerialization<string>.ReadValue = (FastBufferReader reader, out string value) =>
|
||||||
@@ -1079,6 +1039,10 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
variable.ReadField(reader);
|
variable.ReadField(reader);
|
||||||
Assert.AreEqual("012345", variable.Value);
|
Assert.AreEqual("012345", variable.Value);
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Assert.True(NetworkVariableSerialization<UserNetworkVariableSerialization<string>>.IsDistributedAuthority);
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
UserNetworkVariableSerialization<string>.ReadValue = null;
|
UserNetworkVariableSerialization<string>.ReadValue = null;
|
||||||
@@ -5125,408 +5089,5 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
yield return base.OnTearDown();
|
yield return base.OnTearDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the more generic conditional logic for NetworkList tests
|
|
||||||
/// which can be used with the <see cref="NetcodeIntegrationTest.WaitForConditionOrTimeOut"/>
|
|
||||||
/// that accepts anything derived from the <see cref="ConditionalPredicateBase"/> class
|
|
||||||
/// as a parameter.
|
|
||||||
/// </summary>
|
|
||||||
internal class NetworkListTestPredicate : ConditionalPredicateBase
|
|
||||||
{
|
|
||||||
private const int k_MaxRandomValue = 1000;
|
|
||||||
|
|
||||||
private Dictionary<NetworkListTestStates, Func<bool>> m_StateFunctions;
|
|
||||||
|
|
||||||
// Player1 component on the Server
|
|
||||||
private NetworkVariableTest m_Player1OnServer;
|
|
||||||
|
|
||||||
// Player1 component on client1
|
|
||||||
private NetworkVariableTest m_Player1OnClient1;
|
|
||||||
|
|
||||||
private string m_TestStageFailedMessage;
|
|
||||||
|
|
||||||
public enum NetworkListTestStates
|
|
||||||
{
|
|
||||||
Add,
|
|
||||||
ContainsLarge,
|
|
||||||
Contains,
|
|
||||||
VerifyData,
|
|
||||||
IndexOf,
|
|
||||||
}
|
|
||||||
|
|
||||||
private NetworkListTestStates m_NetworkListTestState;
|
|
||||||
|
|
||||||
public void SetNetworkListTestState(NetworkListTestStates networkListTestState)
|
|
||||||
{
|
|
||||||
m_NetworkListTestState = networkListTestState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the condition has been reached for the current NetworkListTestState
|
|
||||||
/// </summary>
|
|
||||||
protected override bool OnHasConditionBeenReached()
|
|
||||||
{
|
|
||||||
var isStateRegistered = m_StateFunctions.ContainsKey(m_NetworkListTestState);
|
|
||||||
Assert.IsTrue(isStateRegistered);
|
|
||||||
return m_StateFunctions[m_NetworkListTestState].Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides all information about the players for both sides for simplicity and informative sake.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string ConditionFailedInfo()
|
|
||||||
{
|
|
||||||
return $"{m_NetworkListTestState} condition test failed:\n Server List Count: {m_Player1OnServer.TheList.Count} vs Client List Count: {m_Player1OnClient1.TheList.Count}\n" +
|
|
||||||
$"Server List Count: {m_Player1OnServer.TheLargeList.Count} vs Client List Count: {m_Player1OnClient1.TheLargeList.Count}\n" +
|
|
||||||
$"Server Delegate Triggered: {m_Player1OnServer.ListDelegateTriggered} | Client Delegate Triggered: {m_Player1OnClient1.ListDelegateTriggered}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When finished, check if a time out occurred and if so assert and provide meaningful information to troubleshoot why
|
|
||||||
/// </summary>
|
|
||||||
protected override void OnFinished()
|
|
||||||
{
|
|
||||||
Assert.IsFalse(TimedOut, $"{nameof(NetworkListTestPredicate)} timed out waiting for the {m_NetworkListTestState} condition to be reached! \n" + ConditionFailedInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uses the ArrayOperator and validates that on both sides the count and values are the same
|
|
||||||
private bool OnVerifyData()
|
|
||||||
{
|
|
||||||
// Wait until both sides have the same number of elements
|
|
||||||
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the client values against the server values to make sure they match
|
|
||||||
for (int i = 0; i < m_Player1OnServer.TheList.Count; i++)
|
|
||||||
{
|
|
||||||
if (m_Player1OnServer.TheList[i] != m_Player1OnClient1.TheList[i])
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Verifies the data count, values, and that the ListDelegate on both sides was triggered
|
|
||||||
/// </summary>
|
|
||||||
private bool OnAdd()
|
|
||||||
{
|
|
||||||
bool wasTriggerred = m_Player1OnServer.ListDelegateTriggered && m_Player1OnClient1.ListDelegateTriggered;
|
|
||||||
return wasTriggerred && OnVerifyData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The current version of this test only verified the count of the large list, so that is what this does
|
|
||||||
/// </summary>
|
|
||||||
private bool OnContainsLarge()
|
|
||||||
{
|
|
||||||
return m_Player1OnServer.TheLargeList.Count == m_Player1OnClient1.TheLargeList.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tests NetworkList.Contains which also verifies all values are the same on both sides
|
|
||||||
/// </summary>
|
|
||||||
private bool OnContains()
|
|
||||||
{
|
|
||||||
// Wait until both sides have the same number of elements
|
|
||||||
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse through all server values and use the NetworkList.Contains method to check if the value is in the list on the client side
|
|
||||||
foreach (var serverValue in m_Player1OnServer.TheList)
|
|
||||||
{
|
|
||||||
if (!m_Player1OnClient1.TheList.Contains(serverValue))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tests NetworkList.IndexOf and verifies that all values are aligned on both sides
|
|
||||||
/// </summary>
|
|
||||||
private bool OnIndexOf()
|
|
||||||
{
|
|
||||||
foreach (var serverSideValue in m_Player1OnServer.TheList)
|
|
||||||
{
|
|
||||||
var indexToTest = m_Player1OnServer.TheList.IndexOf(serverSideValue);
|
|
||||||
if (indexToTest != m_Player1OnServer.TheList.IndexOf(serverSideValue))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVariableTest player1OnClient1, NetworkListTestStates networkListTestState, int elementCount)
|
|
||||||
{
|
|
||||||
m_NetworkListTestState = networkListTestState;
|
|
||||||
m_Player1OnServer = player1OnServer;
|
|
||||||
m_Player1OnClient1 = player1OnClient1;
|
|
||||||
m_StateFunctions = new Dictionary<NetworkListTestStates, Func<bool>>
|
|
||||||
{
|
|
||||||
{ NetworkListTestStates.Add, OnAdd },
|
|
||||||
{ NetworkListTestStates.ContainsLarge, OnContainsLarge },
|
|
||||||
{ NetworkListTestStates.Contains, OnContains },
|
|
||||||
{ NetworkListTestStates.VerifyData, OnVerifyData },
|
|
||||||
{ NetworkListTestStates.IndexOf, OnIndexOf }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (networkListTestState == NetworkListTestStates.ContainsLarge)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < elementCount; ++i)
|
|
||||||
{
|
|
||||||
m_Player1OnServer.TheLargeList.Add(new FixedString128Bytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < elementCount; i++)
|
|
||||||
{
|
|
||||||
m_Player1OnServer.TheList.Add(Random.Range(0, k_MaxRandomValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestFixtureSource(nameof(TestDataSource))]
|
|
||||||
internal class NetworkVariableInheritanceTests : NetcodeIntegrationTest
|
|
||||||
{
|
|
||||||
public NetworkVariableInheritanceTests(HostOrServer hostOrServer)
|
|
||||||
: base(hostOrServer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int NumberOfClients => 2;
|
|
||||||
|
|
||||||
public static IEnumerable<TestFixtureData> TestDataSource() =>
|
|
||||||
Enum.GetValues(typeof(HostOrServer)).OfType<HostOrServer>().Select(x => new TestFixtureData(x));
|
|
||||||
|
|
||||||
internal class ComponentA : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public NetworkVariable<int> PublicFieldA = new NetworkVariable<int>(1);
|
|
||||||
protected NetworkVariable<int> m_ProtectedFieldA = new NetworkVariable<int>(2);
|
|
||||||
private NetworkVariable<int> m_PrivateFieldA = new NetworkVariable<int>(3);
|
|
||||||
|
|
||||||
public void ChangeValuesA(int pub, int pro, int pri)
|
|
||||||
{
|
|
||||||
PublicFieldA.Value = pub;
|
|
||||||
m_ProtectedFieldA.Value = pro;
|
|
||||||
m_PrivateFieldA.Value = pri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CompareValuesA(ComponentA other)
|
|
||||||
{
|
|
||||||
return PublicFieldA.Value == other.PublicFieldA.Value &&
|
|
||||||
m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value &&
|
|
||||||
m_PrivateFieldA.Value == other.m_PrivateFieldA.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ComponentB : ComponentA
|
|
||||||
{
|
|
||||||
public NetworkVariable<int> PublicFieldB = new NetworkVariable<int>(11);
|
|
||||||
protected NetworkVariable<int> m_ProtectedFieldB = new NetworkVariable<int>(22);
|
|
||||||
private NetworkVariable<int> m_PrivateFieldB = new NetworkVariable<int>(33);
|
|
||||||
|
|
||||||
public void ChangeValuesB(int pub, int pro, int pri)
|
|
||||||
{
|
|
||||||
PublicFieldB.Value = pub;
|
|
||||||
m_ProtectedFieldB.Value = pro;
|
|
||||||
m_PrivateFieldB.Value = pri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CompareValuesB(ComponentB other)
|
|
||||||
{
|
|
||||||
return PublicFieldB.Value == other.PublicFieldB.Value &&
|
|
||||||
m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value &&
|
|
||||||
m_PrivateFieldB.Value == other.m_PrivateFieldB.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ComponentC : ComponentB
|
|
||||||
{
|
|
||||||
public NetworkVariable<int> PublicFieldC = new NetworkVariable<int>(111);
|
|
||||||
protected NetworkVariable<int> m_ProtectedFieldC = new NetworkVariable<int>(222);
|
|
||||||
private NetworkVariable<int> m_PrivateFieldC = new NetworkVariable<int>(333);
|
|
||||||
|
|
||||||
public void ChangeValuesC(int pub, int pro, int pri)
|
|
||||||
{
|
|
||||||
PublicFieldC.Value = pub;
|
|
||||||
m_ProtectedFieldA.Value = pro;
|
|
||||||
m_PrivateFieldC.Value = pri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CompareValuesC(ComponentC other)
|
|
||||||
{
|
|
||||||
return PublicFieldC.Value == other.PublicFieldC.Value &&
|
|
||||||
m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value &&
|
|
||||||
m_PrivateFieldC.Value == other.m_PrivateFieldC.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private GameObject m_TestObjectPrefab;
|
|
||||||
private ulong m_TestObjectId = 0;
|
|
||||||
|
|
||||||
protected override void OnOneTimeSetup()
|
|
||||||
{
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = true;
|
|
||||||
base.OnOneTimeSetup();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnOneTimeTearDown()
|
|
||||||
{
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = false;
|
|
||||||
base.OnOneTimeTearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnServerAndClientsCreated()
|
|
||||||
{
|
|
||||||
m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]");
|
|
||||||
m_TestObjectPrefab.AddComponent<ComponentA>();
|
|
||||||
m_TestObjectPrefab.AddComponent<ComponentB>();
|
|
||||||
m_TestObjectPrefab.AddComponent<ComponentC>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerator OnServerAndClientsConnected()
|
|
||||||
{
|
|
||||||
var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>();
|
|
||||||
m_TestObjectId = serverTestObject.NetworkObjectId;
|
|
||||||
|
|
||||||
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
|
||||||
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
|
||||||
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
|
||||||
|
|
||||||
serverTestComponentA.ChangeValuesA(1000, 2000, 3000);
|
|
||||||
serverTestComponentB.ChangeValuesA(1000, 2000, 3000);
|
|
||||||
serverTestComponentB.ChangeValuesB(1100, 2200, 3300);
|
|
||||||
serverTestComponentC.ChangeValuesA(1000, 2000, 3000);
|
|
||||||
serverTestComponentC.ChangeValuesB(1100, 2200, 3300);
|
|
||||||
serverTestComponentC.ChangeValuesC(1110, 2220, 3330);
|
|
||||||
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckTestObjectComponentValuesOnAll()
|
|
||||||
{
|
|
||||||
var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
|
||||||
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
|
||||||
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
|
||||||
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
|
||||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
|
||||||
{
|
|
||||||
var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
|
||||||
var clientTestComponentA = clientTestObject.GetComponent<ComponentA>();
|
|
||||||
var clientTestComponentB = clientTestObject.GetComponent<ComponentB>();
|
|
||||||
var clientTestComponentC = clientTestObject.GetComponent<ComponentC>();
|
|
||||||
if (!serverTestComponentA.CompareValuesA(clientTestComponentA) ||
|
|
||||||
!serverTestComponentB.CompareValuesA(clientTestComponentB) ||
|
|
||||||
!serverTestComponentB.CompareValuesB(clientTestComponentB) ||
|
|
||||||
!serverTestComponentC.CompareValuesA(clientTestComponentC) ||
|
|
||||||
!serverTestComponentC.CompareValuesB(clientTestComponentC) ||
|
|
||||||
!serverTestComponentC.CompareValuesC(clientTestComponentC))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator TestInheritedFields()
|
|
||||||
{
|
|
||||||
yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll);
|
|
||||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class NetvarDespawnShutdown : NetworkBehaviour
|
|
||||||
{
|
|
||||||
private NetworkVariable<int> m_IntNetworkVariable = new NetworkVariable<int>();
|
|
||||||
private NetworkList<int> m_IntList;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
m_IntList = new NetworkList<int>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnNetworkDespawn()
|
|
||||||
{
|
|
||||||
if (IsServer)
|
|
||||||
{
|
|
||||||
m_IntNetworkVariable.Value = 5;
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
{
|
|
||||||
m_IntList.Add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.OnNetworkDespawn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validates that setting values for NetworkVariable or NetworkList during the
|
|
||||||
/// OnNetworkDespawn method will not cause an exception to occur.
|
|
||||||
/// </summary>
|
|
||||||
internal class NetworkVariableModifyOnNetworkDespawn : NetcodeIntegrationTest
|
|
||||||
{
|
|
||||||
protected override int NumberOfClients => 1;
|
|
||||||
|
|
||||||
private GameObject m_TestPrefab;
|
|
||||||
|
|
||||||
protected override void OnOneTimeSetup()
|
|
||||||
{
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = true;
|
|
||||||
base.OnOneTimeSetup();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnOneTimeTearDown()
|
|
||||||
{
|
|
||||||
NetworkVariableBase.IgnoreInitializeWarning = false;
|
|
||||||
base.OnOneTimeTearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnServerAndClientsCreated()
|
|
||||||
{
|
|
||||||
m_TestPrefab = CreateNetworkObjectPrefab("NetVarDespawn");
|
|
||||||
m_TestPrefab.AddComponent<NetvarDespawnShutdown>();
|
|
||||||
base.OnServerAndClientsCreated();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool OnClientSpawnedTestPrefab(ulong networkObjectId)
|
|
||||||
{
|
|
||||||
var clientId = m_ClientNetworkManagers[0].LocalClientId;
|
|
||||||
if (!s_GlobalNetworkObjects.ContainsKey(clientId))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!s_GlobalNetworkObjects[clientId].ContainsKey(networkObjectId))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator ModifyNetworkVariableOrListOnNetworkDespawn()
|
|
||||||
{
|
|
||||||
var instance = SpawnObject(m_TestPrefab, m_ServerNetworkManager);
|
|
||||||
yield return WaitForConditionOrTimeOut(() => OnClientSpawnedTestPrefab(instance.GetComponent<NetworkObject>().NetworkObjectId));
|
|
||||||
m_ServerNetworkManager.Shutdown();
|
|
||||||
// As long as no excetptions occur, the test passes.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Unity.Netcode.TestHelpers.Runtime;
|
using Unity.Netcode.TestHelpers.Runtime;
|
||||||
@@ -50,7 +49,6 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
public override void OnNetworkSpawn()
|
public override void OnNetworkSpawn()
|
||||||
{
|
{
|
||||||
Objects[CurrentlySpawning, NetworkManager.LocalClientId] = GetComponent<OwnerPermissionObject>();
|
Objects[CurrentlySpawning, NetworkManager.LocalClientId] = GetComponent<OwnerPermissionObject>();
|
||||||
//Debug.Log($"Object index ({CurrentlySpawning}) spawned on client {NetworkManager.LocalClientId}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
@@ -85,6 +83,8 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal class OwnerPermissionHideTests : NetcodeIntegrationTest
|
internal class OwnerPermissionHideTests : NetcodeIntegrationTest
|
||||||
{
|
{
|
||||||
protected override int NumberOfClients => 2;
|
protected override int NumberOfClients => 2;
|
||||||
@@ -130,70 +130,44 @@ namespace Unity.Netcode.RuntimeTests
|
|||||||
for (var clientWriting = 0; clientWriting < 3; clientWriting++)
|
for (var clientWriting = 0; clientWriting < 3; clientWriting++)
|
||||||
{
|
{
|
||||||
// ==== Server-writable NetworkVariable ====
|
// ==== Server-writable NetworkVariable ====
|
||||||
var gotException = false;
|
|
||||||
VerboseDebug($"Writing to server-write variable on object {objectIndex} on client {clientWriting}");
|
VerboseDebug($"Writing to server-write variable on object {objectIndex} on client {clientWriting}");
|
||||||
|
|
||||||
try
|
nextValueToWrite++;
|
||||||
|
if (clientWriting != serverIndex)
|
||||||
{
|
{
|
||||||
nextValueToWrite++;
|
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.GetWritePermissionError());
|
||||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite;
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite;
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify server-owned netvar can only be written by server
|
|
||||||
Debug.Assert(gotException == (clientWriting != serverIndex));
|
|
||||||
|
|
||||||
// ==== Owner-writable NetworkVariable ====
|
// ==== Owner-writable NetworkVariable ====
|
||||||
gotException = false;
|
|
||||||
VerboseDebug($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}");
|
VerboseDebug($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}");
|
||||||
|
|
||||||
try
|
nextValueToWrite++;
|
||||||
|
if (clientWriting != objectIndex)
|
||||||
{
|
{
|
||||||
nextValueToWrite++;
|
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.GetWritePermissionError());
|
||||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite;
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite;
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify client-owned netvar can only be written by owner
|
|
||||||
Debug.Assert(gotException == (clientWriting != objectIndex));
|
|
||||||
|
|
||||||
// ==== Server-writable NetworkList ====
|
// ==== Server-writable NetworkList ====
|
||||||
gotException = false;
|
VerboseDebug($"Writing to [Add] server-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||||
|
|
||||||
try
|
nextValueToWrite++;
|
||||||
|
if (clientWriting != serverIndex)
|
||||||
{
|
{
|
||||||
nextValueToWrite++;
|
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.GetWritePermissionError());
|
||||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite);
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify server-owned networkList can only be written by server
|
|
||||||
Debug.Assert(gotException == (clientWriting != serverIndex));
|
|
||||||
|
|
||||||
// ==== Owner-writable NetworkList ====
|
// ==== Owner-writable NetworkList ====
|
||||||
gotException = false;
|
VerboseDebug($"Writing to [Add] owner-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||||
|
|
||||||
try
|
nextValueToWrite++;
|
||||||
|
if (clientWriting != objectIndex)
|
||||||
{
|
{
|
||||||
nextValueToWrite++;
|
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.GetWritePermissionError());
|
||||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite);
|
||||||
{
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify client-owned networkList can only be written by owner
|
|
||||||
Debug.Assert(gotException == (clientWriting != objectIndex));
|
|
||||||
|
|
||||||
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
||||||
yield return WaitForTicks(m_ClientNetworkManagers[0], 5);
|
yield return WaitForTicks(m_ClientNetworkManagers[0], 5);
|
||||||
10
package.json
10
package.json
@@ -2,23 +2,23 @@
|
|||||||
"name": "com.unity.netcode.gameobjects",
|
"name": "com.unity.netcode.gameobjects",
|
||||||
"displayName": "Netcode for GameObjects",
|
"displayName": "Netcode for GameObjects",
|
||||||
"description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.",
|
"description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.",
|
||||||
"version": "2.0.0-pre.2",
|
"version": "2.0.0-pre.4",
|
||||||
"unity": "6000.0",
|
"unity": "6000.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.nuget.mono-cecil": "1.11.4",
|
"com.unity.nuget.mono-cecil": "1.11.4",
|
||||||
"com.unity.transport": "2.2.1"
|
"com.unity.transport": "2.3.0"
|
||||||
},
|
},
|
||||||
"_upm": {
|
"_upm": {
|
||||||
"changelog": "### Added\n\n- Added `AnticipatedNetworkVariable<T>`, which adds support for client anticipation of `NetworkVariable` values, allowing for more responsive gameplay. (#2957)\n- Added `AnticipatedNetworkTransform`, which adds support for client anticipation of NetworkTransforms. (#2957)\n- Added `NetworkVariableBase.ExceedsDirtinessThreshold` to allow network variables to throttle updates by only sending updates when the difference between the current and previous values exceeds a threshold. (This is exposed in `NetworkVariable<T>` with the callback `NetworkVariable<T>.CheckExceedsDirtinessThreshold`). (#2957)\n- Added `NetworkVariableUpdateTraits`, which add additional throttling support: `MinSecondsBetweenUpdates` will prevent the `NetworkVariable` from sending updates more often than the specified time period (even if it exceeds the dirtiness threshold), while `MaxSecondsBetweenUpdates` will force a dirty `NetworkVariable` to send an update after the specified time period even if it has not yet exceeded the dirtiness threshold. (#2957)\n- Added virtual method `NetworkVariableBase.OnInitialize` which can be used by `NetworkVariable` subclasses to add initialization code. (#2957)\n- Added `NetworkTime.TickWithPartial`, which represents the current tick as a double that includes the fractional/partial tick value. (#2957)\n- Added `NetworkTickSystem.AnticipationTick`, which can be helpful with implementation of client anticipation. This value represents the tick the current local client was at at the beginning of the most recent network round trip, which enables it to correlate server update ticks with the client tick that may have triggered them. (#2957)\n- Added event `NetworkManager.OnSessionOwnerPromoted` that is invoked when a new session owner promotion occurs. (#2948)\n- Added `NetworkRigidBodyBase.GetLinearVelocity` and `NetworkRigidBodyBase.SetLinearVelocity` convenience/helper methods. (#2948)\n- Added `NetworkRigidBodyBase.GetAngularVelocity` and `NetworkRigidBodyBase.SetAngularVelocity` convenience/helper methods. (#2948)\n\n### Fixed\n\n- Fixed issue when `NetworkTransform` half float precision is enabled and ownership changes the current base position was not being synchronized. (#2948)\n- Fixed issue where `OnClientConnected` not being invoked on the session owner when connecting to a new distributed authority session. (#2948)\n- Fixed issue where Rigidbody micro-motion (i.e. relatively small velocities) would result in non-authority instances slightly stuttering as the body would come to a rest (i.e. no motion). Now, the threshold value can increase at higher velocities and can decrease slightly below the provided threshold to account for this. (#2948)\n\n### Changed\n\n- Changed `NetworkAnimator` no longer requires the `Animator` component to exist on the same `GameObject`. (#2957)\n- Changed `NetworkObjectReference` and `NetworkBehaviourReference` to allow null references when constructing and serializing. (#2957)\n- Changed the client's owned objects is now returned (`NetworkClient` and `NetworkSpawnManager`) as an array as opposed to a list for performance purposes. (#2948)\n- Changed `NetworkTransfrom.TryCommitTransformToServer` to be internal as it will be removed by the final 2.0.0 release. (#2948)\n- Changed `NetworkTransformEditor.OnEnable` to a virtual method to be able to customize a `NetworkTransform` derived class by creating a derived editor control from `NetworkTransformEditor`. (#2948)"
|
"changelog": "### Added\n\n- Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3004)\n\n### Fixed\n\n- Fixed issue where nested `NetworkTransform` components were not getting updated. (#3016)\n- Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3012)\n- Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#3009)\n- Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#3008)\n- Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3004)\n- Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3004)\n- Fixed issue where `NotAuthorityTarget` would include the service observer in the list of targets to send the RPC to as opposed to excluding the service observer as it should. (#3000)\n- Fixed issue where `ProxyRpcTargetGroup` could attempt to send a message if there were no targets to send to. (#3000)\n\n### Changed\n\n- Changed `NetworkAnimator` to automatically switch to owner authoritative mode when using a distributed authority network topology. (#3021)\n- Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004)\n- Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004)"
|
||||||
},
|
},
|
||||||
"upmCi": {
|
"upmCi": {
|
||||||
"footprint": "dffe7543c19c2670755cc7da27e1d4522c9414a9"
|
"footprint": "48286e9f7b0e053fe7f7b524bafc69a99c2906fc"
|
||||||
},
|
},
|
||||||
"documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.0/manual/index.html",
|
"documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.0/manual/index.html",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git",
|
"url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"revision": "2ecbd14351cac29ab3a18cc159c0a82513e9d241"
|
"revision": "2802dfcd13c3be1ac356191cc87d1559203d2db3"
|
||||||
},
|
},
|
||||||
"samples": [
|
"samples": [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user