com.unity.netcode.gameobjects@2.2.0
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [2.2.0] - 2024-12-12 ### Added - Added `NetworkObject.OwnershipStatus.SessionOwner` to allow Network Objects to be distributable and only owned by the Session Owner. This flag will override all other `OwnershipStatus` flags. (#3175) - Added `UnityTransport.GetEndpoint` method to provide a way to obtain `NetworkEndpoint` information of a connection via client identifier. (#3130) - Added `NetworkTransport.OnEarlyUpdate` and `NetworkTransport.OnPostLateUpdate` methods to provide more control over handling transport related events at the start and end of each frame. (#3113) ### Fixed - Fixed issue where the server, host, or session owner would not populate the in-scene place `NetworkObject` table if the scene was loaded prior to starting the `NetworkManager`. (#3177) - Fixed issue where the `NetworkObjectIdHash` value could be incorrect when entering play mode while still in prefab edit mode with pending changes and using MPPM. (#3162) - Fixed issue where a sever only `NetworkManager` instance would spawn the actual `NetworkPrefab`'s `GameObject` as opposed to creating an instance of it. (#3160) - Fixed issue where only the session owner (as opposed to all clients) would handle spawning prefab overrides properly when using a distributed authority network topology. (#3160) - Fixed issue where an exception was thrown when calling `NetworkManager.Shutdown` after calling `UnityTransport.Shutdown`. (#3118) - Fixed issue where `NetworkList` properties on in-scene placed `NetworkObject`s could cause small memory leaks when entering playmode. (#3147) - Fixed in-scene `NertworkObject` synchronization issue when loading a scene with currently connected clients connected to a session created by a `NetworkManager` started as a server (i.e. not as a host). (#3133) - Fixed issue where a `NetworkManager` started as a server would not add itself as an observer to in-scene placed `NetworkObject`s instantiated and spawned by a scene loading event. (#3133) - Fixed issue where spawning a player using `NetworkObject.InstantiateAndSpawn` or `NetworkSpawnManager.InstantiateAndSpawn` would not update the `NetworkSpawnManager.PlayerObjects` or assign the newly spawned player to the `NetworkClient.PlayerObject`. (#3122) - Fixed issue where queued UnitTransport (NetworkTransport) message batches were being sent on the next frame. They are now sent at the end of the frame during `PostLateUpdate`. (#3113) - Fixed issue where `NotOwnerRpcTarget` or `OwnerRpcTarget` were not using their replacements `NotAuthorityRpcTarget` and `AuthorityRpcTarget` which would invoke a warning. (#3111) - Fixed issue where client is removed as an observer from spawned objects when their player instance is despawned. (#3110) - Fixed issue where `NetworkAnimator` would statically allocate write buffer space for `Animator` parameters that could cause a write error if the number of parameters exceeded the space allocated. (#3108) ### Changed - In-scene placed `NetworkObject`s have been made distributable when balancing object distribution after a connection event. (#3175) - Optimised `NetworkVariable` and `NetworkTransform` related packets when in Distributed Authority mode. - The Debug Simulator section of the Unity Transport component was removed. This section was not functional anymore and users are now recommended to use the more featureful [Network Simulator](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/) tool from the Multiplayer Tools package instead. (#3121)
This commit is contained in:
@@ -32,7 +32,8 @@ namespace Unity.Netcode.Components
|
||||
/// </summary>
|
||||
public struct NetworkTransformState : INetworkSerializable
|
||||
{
|
||||
private const int k_InLocalSpaceBit = 0x00000001; // Persists between state updates (authority dictates if this is set)
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_InLocalSpaceBit = 0x00000001;
|
||||
private const int k_PositionXBit = 0x00000002;
|
||||
private const int k_PositionYBit = 0x00000004;
|
||||
private const int k_PositionZBit = 0x00000008;
|
||||
@@ -43,18 +44,25 @@ namespace Unity.Netcode.Components
|
||||
private const int k_ScaleYBit = 0x00000100;
|
||||
private const int k_ScaleZBit = 0x00000200;
|
||||
private const int k_TeleportingBit = 0x00000400;
|
||||
private const int k_Interpolate = 0x00000800; // Persists between state updates (authority dictates if this is set)
|
||||
private const int k_QuaternionSync = 0x00001000; // Persists between state updates (authority dictates if this is set)
|
||||
private const int k_QuaternionCompress = 0x00002000; // Persists between state updates (authority dictates if this is set)
|
||||
private const int k_UseHalfFloats = 0x00004000; // Persists between state updates (authority dictates if this is set)
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_Interpolate = 0x00000800;
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_QuaternionSync = 0x00001000;
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_QuaternionCompress = 0x00002000;
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_UseHalfFloats = 0x00004000;
|
||||
private const int k_Synchronization = 0x00008000;
|
||||
private const int k_PositionSlerp = 0x00010000; // Persists between state updates (authority dictates if this is set)
|
||||
private const int k_IsParented = 0x00020000; // When parented and synchronizing, we need to have both lossy and local scale due to varying spawn order
|
||||
// Persists between state updates (authority dictates if this is set)
|
||||
private const int k_PositionSlerp = 0x00010000;
|
||||
// When parented and synchronizing, we need to have both lossy and local scale due to varying spawn order
|
||||
private const int k_IsParented = 0x00020000;
|
||||
private const int k_SynchBaseHalfFloat = 0x00040000;
|
||||
private const int k_ReliableSequenced = 0x00080000;
|
||||
private const int k_UseUnreliableDeltas = 0x00100000;
|
||||
private const int k_UnreliableFrameSync = 0x00200000;
|
||||
private const int k_TrackStateId = 0x10000000; // (Internal Debugging) When set each state update will contain a state identifier
|
||||
// (Internal Debugging) When set each state update will contain a state identifier
|
||||
private const int k_TrackStateId = 0x10000000;
|
||||
|
||||
// Stores persistent and state relative flags
|
||||
private uint m_Bitset;
|
||||
@@ -409,8 +417,8 @@ namespace Unity.Netcode.Components
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether this state update was a frame synchronization when
|
||||
/// UseUnreliableDeltas is enabled. When set, the entire transform will
|
||||
/// Returns whether this state update was a frame synchronization when
|
||||
/// UseUnreliableDeltas is enabled. When set, the entire transform will
|
||||
/// be or has been synchronized.
|
||||
/// </summary>
|
||||
public bool IsUnreliableFrameSync()
|
||||
@@ -929,8 +937,6 @@ namespace Unity.Netcode.Components
|
||||
#endregion
|
||||
|
||||
#region PROPERTIES AND GENERAL METHODS
|
||||
|
||||
|
||||
public enum AuthorityModes
|
||||
{
|
||||
Server,
|
||||
@@ -1370,7 +1376,8 @@ namespace Unity.Netcode.Components
|
||||
|
||||
private BufferedLinearInterpolatorVector3 m_PositionInterpolator;
|
||||
private BufferedLinearInterpolatorVector3 m_ScaleInterpolator;
|
||||
private BufferedLinearInterpolatorQuaternion m_RotationInterpolator; // rotation is a single Quaternion since each Euler axis will affect the quaternion's final value
|
||||
// rotation is a single Quaternion since each Euler axis will affect the quaternion's final value
|
||||
private BufferedLinearInterpolatorQuaternion m_RotationInterpolator;
|
||||
|
||||
// The previous network state
|
||||
private NetworkTransformState m_OldState = new NetworkTransformState();
|
||||
@@ -1643,11 +1650,11 @@ namespace Unity.Netcode.Components
|
||||
Debug.LogException(ex);
|
||||
}
|
||||
|
||||
// The below is part of assuring we only send a frame synch, when sending unreliable deltas, if
|
||||
// The below is part of assuring we only send a frame synch, when sending unreliable deltas, if
|
||||
// we have already sent at least one unreliable delta state update. At this point in the callstack,
|
||||
// a delta state update has just been sent in the above UpdateTransformState() call and as long as
|
||||
// we didn't send a frame synch and we are not synchronizing then we know at least one unreliable
|
||||
// delta has been sent. Under this scenario, we should start checking for this instance's alloted
|
||||
// delta has been sent. Under this scenario, we should start checking for this instance's alloted
|
||||
// frame synch "tick slot". Once we send a frame synch, if no other deltas occur after that
|
||||
// (i.e. the object is at rest) then we will stop sending frame synch's until the object begins
|
||||
// moving, rotating, or scaling again.
|
||||
@@ -1964,7 +1971,7 @@ namespace Unity.Netcode.Components
|
||||
|
||||
networkState.NetworkDeltaPosition = m_HalfPositionState;
|
||||
|
||||
// If ownership offset is greater or we are doing an axial synchronization then synchronize the base position
|
||||
// If ownership offset is greater or we are doing an axial synchronization then synchronize the base position
|
||||
if ((m_HalfFloatTargetTickOwnership > m_CachedNetworkManager.ServerTime.Tick || isAxisSync) && !networkState.IsTeleportingNextFrame)
|
||||
{
|
||||
networkState.SynchronizeBaseHalfFloat = true;
|
||||
@@ -3403,7 +3410,7 @@ namespace Unity.Netcode.Components
|
||||
/// - Local space to local space (<see cref="NetworkObject"/> parent to <see cref="NetworkObject"/> parent)
|
||||
/// Will all smoothly transition while interpolation is enabled.
|
||||
/// (Does not work if using a <see cref="Rigidbody"/> or <see cref="Rigidbody2D"/> for motion)
|
||||
///
|
||||
///
|
||||
/// When a parent changes, non-authoritative instances should:<br />
|
||||
/// - Apply the resultant position, rotation, and scale from the parenting action.<br />
|
||||
/// - Clear interpolators (even if not enabled on this frame)<br />
|
||||
@@ -3575,7 +3582,7 @@ namespace Unity.Netcode.Components
|
||||
|
||||
var transformToCommit = transform;
|
||||
|
||||
// Explicit set states are cumulative during a fractional tick period of time (i.e. each SetState invocation will
|
||||
// Explicit set states are cumulative during a fractional tick period of time (i.e. each SetState invocation will
|
||||
// update the axial deltas to whatever changes are applied). As such, we need to preserve the dirty and explicit
|
||||
// state flags.
|
||||
var stateWasDirty = m_LocalAuthoritativeNetworkState.IsDirty;
|
||||
@@ -3658,7 +3665,7 @@ namespace Unity.Netcode.Components
|
||||
|
||||
var serverTime = m_CachedNetworkManager.ServerTime;
|
||||
var cachedServerTime = serverTime.Time;
|
||||
//var offset = (float)serverTime.TickOffset;
|
||||
// var offset = (float)serverTime.TickOffset;
|
||||
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
|
||||
var cachedDeltaTime = m_UseRigidbodyForMotion ? m_CachedNetworkManager.RealTimeProvider.FixedDeltaTime : m_CachedNetworkManager.RealTimeProvider.DeltaTime;
|
||||
#else
|
||||
@@ -3669,7 +3676,7 @@ namespace Unity.Netcode.Components
|
||||
// is to make their cachedRenderTime run 2 ticks behind.
|
||||
|
||||
// TODO: This could most likely just always be 2
|
||||
//var ticksAgo = ((!IsServerAuthoritative() && !IsServer) || m_CachedNetworkManager.DistributedAuthorityMode) && !m_CachedNetworkManager.DAHost ? 2 : 1;
|
||||
// var ticksAgo = ((!IsServerAuthoritative() && !IsServer) || m_CachedNetworkManager.DistributedAuthorityMode) && !m_CachedNetworkManager.DAHost ? 2 : 1;
|
||||
var ticksAgo = 2;
|
||||
|
||||
var cachedRenderTime = serverTime.TimeTicksAgo(ticksAgo).Time;
|
||||
@@ -3746,7 +3753,7 @@ namespace Unity.Netcode.Components
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the <see cref="NetworkTransform"/> is <see cref="AuthorityModes.Server"/> or <see cref="AuthorityModes.Owner"/> based on the <see cref="AuthorityMode"/> property.
|
||||
/// You can override this method to control this logic.
|
||||
/// You can override this method to control this logic.
|
||||
/// </summary>
|
||||
/// <returns><see cref="true"/> or <see cref="false"/></returns>
|
||||
protected virtual bool OnIsServerAuthoritative()
|
||||
@@ -3772,7 +3779,6 @@ namespace Unity.Netcode.Components
|
||||
return OnIsServerAuthoritative();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MESSAGE HANDLING
|
||||
@@ -3964,7 +3970,7 @@ namespace Unity.Netcode.Components
|
||||
{
|
||||
return 2 * m_TickFrequency;
|
||||
// TODO: We need an RTT that updates regularly and not just when the client sends packets
|
||||
//return Mathf.Max(1.0f, TicksAgo) * m_TickFrequency;
|
||||
// return Mathf.Max(1.0f, TicksAgo) * m_TickFrequency;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3974,25 +3980,25 @@ namespace Unity.Netcode.Components
|
||||
private void TickUpdate()
|
||||
{
|
||||
// TODO: We need an RTT that updates regularly and not just when the client sends packets
|
||||
//if (m_UnityTransport != null)
|
||||
//{
|
||||
// // Determine the desired ticks ago by the RTT (this really should be the combination of the
|
||||
// // authority and non-authority 1/2 RTT but in the end anything beyond 300ms is considered very poor
|
||||
// // network quality so latent interpolation is going to be expected).
|
||||
// var rtt = Mathf.Max(m_TickInMS, m_UnityTransport.GetCurrentRtt(NetworkManager.ServerClientId));
|
||||
// m_TicksAgoSamples[m_TickSampleIndex] = Mathf.Max(1, (int)(rtt * m_TickFrequency));
|
||||
// var tickAgoSum = 0.0f;
|
||||
// foreach (var tickAgo in m_TicksAgoSamples)
|
||||
// {
|
||||
// tickAgoSum += tickAgo;
|
||||
// }
|
||||
// m_PreviousTicksAgo = TicksAgo;
|
||||
// TicksAgo = Mathf.Lerp(m_PreviousTicksAgo, tickAgoSum / m_TickRate, m_TickFrequency);
|
||||
// m_TickSampleIndex = (m_TickSampleIndex + 1) % m_TickRate;
|
||||
// // Get the partial tick value for when this is all calculated to provide an offset for determining
|
||||
// // the relative starting interpolation point for the next update
|
||||
// Offset = m_OffsetTickFrequency * (Mathf.Max(2, TicksAgo) - (int)TicksAgo);
|
||||
//}
|
||||
// if (m_UnityTransport != null)
|
||||
// {
|
||||
// // Determine the desired ticks ago by the RTT (this really should be the combination of the
|
||||
// // authority and non-authority 1/2 RTT but in the end anything beyond 300ms is considered very poor
|
||||
// // network quality so latent interpolation is going to be expected).
|
||||
// var rtt = Mathf.Max(m_TickInMS, m_UnityTransport.GetCurrentRtt(NetworkManager.ServerClientId));
|
||||
// m_TicksAgoSamples[m_TickSampleIndex] = Mathf.Max(1, (int)(rtt * m_TickFrequency));
|
||||
// var tickAgoSum = 0.0f;
|
||||
// foreach (var tickAgo in m_TicksAgoSamples)
|
||||
// {
|
||||
// tickAgoSum += tickAgo;
|
||||
// }
|
||||
// m_PreviousTicksAgo = TicksAgo;
|
||||
// TicksAgo = Mathf.Lerp(m_PreviousTicksAgo, tickAgoSum / m_TickRate, m_TickFrequency);
|
||||
// m_TickSampleIndex = (m_TickSampleIndex + 1) % m_TickRate;
|
||||
// // Get the partial tick value for when this is all calculated to provide an offset for determining
|
||||
// // the relative starting interpolation point for the next update
|
||||
// Offset = m_OffsetTickFrequency * (Mathf.Max(2, TicksAgo) - (int)TicksAgo);
|
||||
// }
|
||||
|
||||
// TODO FIX: The local NetworkTickSystem can invoke with the same network tick as before
|
||||
if (m_NetworkManager.ServerTime.Tick <= m_LastTick)
|
||||
@@ -4012,13 +4018,13 @@ namespace Unity.Netcode.Components
|
||||
|
||||
private UnityTransport m_UnityTransport;
|
||||
private float m_TickFrequency;
|
||||
//private float m_OffsetTickFrequency;
|
||||
//private ulong m_TickInMS;
|
||||
//private int m_TickSampleIndex;
|
||||
// private float m_OffsetTickFrequency;
|
||||
// private ulong m_TickInMS;
|
||||
// private int m_TickSampleIndex;
|
||||
private int m_TickRate;
|
||||
public float TicksAgo { get; private set; }
|
||||
//public float Offset { get; private set; }
|
||||
//private float m_PreviousTicksAgo;
|
||||
// public float Offset { get; private set; }
|
||||
// private float m_PreviousTicksAgo;
|
||||
|
||||
private List<float> m_TicksAgoSamples = new List<float>();
|
||||
|
||||
@@ -4032,16 +4038,16 @@ namespace Unity.Netcode.Components
|
||||
//// For the offset, it uses the fractional remainder of the tick to determine the offset.
|
||||
//// In order to keep within tick boundaries, we increment the tick rate by 1 to assure it
|
||||
//// will always be < the tick frequency.
|
||||
//m_OffsetTickFrequency = 1.0f / (m_TickRate + 1);
|
||||
//m_TickInMS = (ulong)(1000 * m_TickFrequency);
|
||||
//m_UnityTransport = m_NetworkManager.NetworkConfig.NetworkTransport as UnityTransport;
|
||||
// m_OffsetTickFrequency = 1.0f / (m_TickRate + 1);
|
||||
// m_TickInMS = (ulong)(1000 * m_TickFrequency);
|
||||
// m_UnityTransport = m_NetworkManager.NetworkConfig.NetworkTransport as UnityTransport;
|
||||
//// Fill the sample with a starting value of 1
|
||||
//for (int i = 0; i < m_TickRate; i++)
|
||||
//{
|
||||
// m_TicksAgoSamples.Add(1f);
|
||||
//}
|
||||
// for (int i = 0; i < m_TickRate; i++)
|
||||
// {
|
||||
// m_TicksAgoSamples.Add(1f);
|
||||
// }
|
||||
TicksAgo = 2f;
|
||||
//m_PreviousTicksAgo = 1f;
|
||||
// m_PreviousTicksAgo = 1f;
|
||||
if (networkManager.IsServer)
|
||||
{
|
||||
networkManager.OnServerStopped += OnNetworkManagerStopped;
|
||||
|
||||
Reference in New Issue
Block a user