com.unity.netcode.gameobjects@1.9.1
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.9.1] - 2024-04-18 ### Added - Added AnticipatedNetworkVariable<T>, which adds support for client anticipation of NetworkVariable values, allowing for more responsive gameplay (#2820) - Added AnticipatedNetworkTransform, which adds support for client anticipation of NetworkTransforms (#2820) - 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) (#2820) - 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. (#2820) - Added virtual method NetworkVariableBase.OnInitialize() which can be used by NetworkVariable subclasses to add initialization code (#2820) - Added virtual method NetworkVariableBase.Update(), which is called once per frame to support behaviors such as interpolation between an anticipated value and an authoritative one. (#2820) - Added NetworkTime.TickWithPartial, which represents the current tick as a double that includes the fractional/partial tick value. (#2820) - 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. (#2820) - `NetworkVariable` now includes built-in support for `NativeHashSet`, `NativeHashMap`, `List`, `HashSet`, and `Dictionary` (#2813) - `NetworkVariable` now includes delta compression for collection values (`NativeList`, `NativeArray`, `NativeHashSet`, `NativeHashMap`, `List`, `HashSet`, `Dictionary`, and `FixedString` types) to save bandwidth by only sending the values that changed. (Note: For `NativeList`, `NativeArray`, and `List`, this algorithm works differently than that used in `NetworkList`. This algorithm will use less bandwidth for "set" and "add" operations, but `NetworkList` is more bandwidth-efficient if you are performing frequent "insert" operations.) (#2813) - `UserNetworkVariableSerialization` now has optional callbacks for `WriteDelta` and `ReadDelta`. If both are provided, they will be used for all serialization operations on NetworkVariables of that type except for the first one for each client. If either is missing, the existing `Write` and `Read` will always be used. (#2813) - Network variables wrapping `INetworkSerializable` types can perform delta serialization by setting `UserNetworkVariableSerialization<T>.WriteDelta` and `UserNetworkVariableSerialization<T>.ReadDelta` for those types. The built-in `INetworkSerializable` serializer will continue to be used for all other serialization operations, but if those callbacks are set, it will call into them on all but the initial serialization to perform delta serialization. (This could be useful if you have a large struct where most values do not change regularly and you want to send only the fields that did change.) (#2813) ### Fixed - Fixed issue where NetworkTransformEditor would throw and exception if you excluded the physics package. (#2871) - Fixed issue where `NetworkTransform` could not properly synchronize its base position when using half float precision. (#2845) - Fixed issue where the host was not invoking `OnClientDisconnectCallback` for its own local client when internally shutting down. (#2822) - Fixed issue where NetworkTransform could potentially attempt to "unregister" a named message prior to it being registered. (#2807) - Fixed issue where in-scene placed `NetworkObject`s with complex nested children `NetworkObject`s (more than one child in depth) would not synchronize properly if WorldPositionStays was set to true. (#2796) ### Changed - Changed `NetworkObjectReference` and `NetworkBehaviourReference` to allow null references when constructing and serializing. (#2874) - Changed `NetworkAnimator` no longer requires the `Animator` component to exist on the same `GameObject`. (#2872) - Changed `NetworkTransform` to now use `NetworkTransformMessage` as opposed to named messages for NetworkTransformState updates. (#2810) - Changed `CustomMessageManager` so it no longer attempts to register or "unregister" a null or empty string and will log an error if this condition occurs. (#2807)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Collections;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -1330,9 +1329,6 @@ namespace Unity.Netcode.Components
|
||||
private Quaternion m_CurrentRotation;
|
||||
private Vector3 m_TargetRotation;
|
||||
|
||||
// Used to for each instance to uniquely identify the named message
|
||||
private string m_MessageName;
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void UpdatePositionInterpolator(Vector3 position, double time, bool resetInterpolator = false)
|
||||
@@ -1428,6 +1424,7 @@ namespace Unity.Netcode.Components
|
||||
/// <param name="targetClientId">the clientId being synchronized (both reading and writing)</param>
|
||||
protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
|
||||
{
|
||||
m_CachedNetworkManager = NetworkManager;
|
||||
var targetClientId = m_TargetIdBeingSynchronized;
|
||||
var synchronizationState = new NetworkTransformState()
|
||||
{
|
||||
@@ -2051,10 +2048,15 @@ namespace Unity.Netcode.Components
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
protected virtual void OnTransformUpdated()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the authoritative state to the transform
|
||||
/// </summary>
|
||||
private void ApplyAuthoritativeState()
|
||||
protected internal void ApplyAuthoritativeState()
|
||||
{
|
||||
var networkState = m_LocalAuthoritativeNetworkState;
|
||||
// The m_CurrentPosition, m_CurrentRotation, and m_CurrentScale values are continually updated
|
||||
@@ -2225,6 +2227,7 @@ namespace Unity.Netcode.Components
|
||||
}
|
||||
transform.localScale = m_CurrentScale;
|
||||
}
|
||||
OnTransformUpdated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2422,6 +2425,7 @@ namespace Unity.Netcode.Components
|
||||
{
|
||||
AddLogEntry(ref newState, NetworkObject.OwnerClientId);
|
||||
}
|
||||
OnTransformUpdated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2590,6 +2594,11 @@ namespace Unity.Netcode.Components
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnBeforeUpdateTransformState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private NetworkTransformState m_OldState = new NetworkTransformState();
|
||||
|
||||
/// <summary>
|
||||
@@ -2613,6 +2622,8 @@ namespace Unity.Netcode.Components
|
||||
// Get the time when this new state was sent
|
||||
newState.SentTime = new NetworkTime(m_CachedNetworkManager.NetworkConfig.TickRate, newState.NetworkTick).Time;
|
||||
|
||||
OnBeforeUpdateTransformState();
|
||||
|
||||
// Apply the new state
|
||||
ApplyUpdatedState(newState);
|
||||
|
||||
@@ -2753,21 +2764,17 @@ namespace Unity.Netcode.Components
|
||||
// Started using this again to avoid the getter processing cost of NetworkBehaviour.NetworkManager
|
||||
m_CachedNetworkManager = NetworkManager;
|
||||
|
||||
// Register a custom named message specifically for this instance
|
||||
m_MessageName = $"NTU_{NetworkObjectId}_{NetworkBehaviourId}";
|
||||
m_CachedNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(m_MessageName, TransformStateUpdate);
|
||||
Initialize();
|
||||
|
||||
if (CanCommitToTransform && UseHalfFloatPrecision)
|
||||
{
|
||||
SetState(GetSpaceRelativePosition(), GetSpaceRelativeRotation(), GetScale(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
// During destroy, use NetworkBehaviour.NetworkManager as opposed to m_CachedNetworkManager
|
||||
if (!NetworkManager.ShutdownInProgress && NetworkManager.CustomMessagingManager != null)
|
||||
{
|
||||
NetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(m_MessageName);
|
||||
}
|
||||
|
||||
DeregisterForTickUpdate(this);
|
||||
|
||||
CanCommitToTransform = false;
|
||||
@@ -3156,79 +3163,23 @@ namespace Unity.Netcode.Components
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives the <see cref="NetworkTransformState"/> named message updates
|
||||
/// Invoked by <see cref="NetworkTransformMessage"/> to update the transform state
|
||||
/// </summary>
|
||||
/// <param name="senderId">authority of the transform</param>
|
||||
/// <param name="messagePayload">serialzied <see cref="NetworkTransformState"/></param>
|
||||
private void TransformStateUpdate(ulong senderId, FastBufferReader messagePayload)
|
||||
/// <param name="networkTransformState"></param>
|
||||
internal void TransformStateUpdate(ref NetworkTransformState networkTransformState)
|
||||
{
|
||||
var ownerAuthoritativeServerSide = !OnIsServerAuthoritative() && IsServer;
|
||||
if (ownerAuthoritativeServerSide && OwnerClientId == NetworkManager.ServerClientId)
|
||||
{
|
||||
// Ownership must have changed, ignore any additional pending messages that might have
|
||||
// come from a previous owner client.
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the previous/old state
|
||||
m_OldState = m_LocalAuthoritativeNetworkState;
|
||||
|
||||
// Save the current payload stream position
|
||||
var currentPosition = messagePayload.Position;
|
||||
// Assign the new incoming state
|
||||
m_LocalAuthoritativeNetworkState = networkTransformState;
|
||||
|
||||
// Deserialize the message (and determine network delivery)
|
||||
messagePayload.ReadNetworkSerializableInPlace(ref m_LocalAuthoritativeNetworkState);
|
||||
|
||||
// Rewind back prior to serialization
|
||||
messagePayload.Seek(currentPosition);
|
||||
|
||||
// Get the network delivery method used to send this state update
|
||||
var networkDelivery = m_LocalAuthoritativeNetworkState.ReliableSequenced ? NetworkDelivery.ReliableSequenced : NetworkDelivery.UnreliableSequenced;
|
||||
|
||||
// Forward owner authoritative messages before doing anything else
|
||||
if (ownerAuthoritativeServerSide)
|
||||
{
|
||||
// Forward the state update if there are any remote clients to foward it to
|
||||
if (m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count > (IsHost ? 2 : 1))
|
||||
{
|
||||
ForwardStateUpdateMessage(messagePayload, networkDelivery);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the message
|
||||
// Apply the state update
|
||||
OnNetworkStateChanged(m_OldState, m_LocalAuthoritativeNetworkState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forwards owner authoritative state updates when received by the server
|
||||
/// </summary>
|
||||
/// <param name="messagePayload">the owner state message payload</param>
|
||||
private unsafe void ForwardStateUpdateMessage(FastBufferReader messagePayload, NetworkDelivery networkDelivery)
|
||||
{
|
||||
var serverAuthoritative = OnIsServerAuthoritative();
|
||||
var currentPosition = messagePayload.Position;
|
||||
var messageSize = messagePayload.Length - currentPosition;
|
||||
var writer = new FastBufferWriter(messageSize, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteBytesSafe(messagePayload.GetUnsafePtr(), messageSize, currentPosition);
|
||||
|
||||
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
{
|
||||
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
|
||||
if (NetworkManager.ServerClientId == clientId || (!serverAuthoritative && clientId == OwnerClientId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
m_CachedNetworkManager.CustomMessagingManager.SendNamedMessage(m_MessageName, clientId, writer, networkDelivery);
|
||||
}
|
||||
}
|
||||
messagePayload.Seek(currentPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends <see cref="NetworkTransformState"/> named message updates by the authority of the transform
|
||||
/// Invoked by the authoritative instance to sends a <see cref="NetworkTransformMessage"/> containing the <see cref="NetworkTransformState"/>
|
||||
/// </summary>
|
||||
private void UpdateTransformState()
|
||||
{
|
||||
@@ -3248,7 +3199,12 @@ namespace Unity.Netcode.Components
|
||||
}
|
||||
var customMessageManager = m_CachedNetworkManager.CustomMessagingManager;
|
||||
|
||||
var writer = new FastBufferWriter(128, Allocator.Temp);
|
||||
var networkTransformMessage = new NetworkTransformMessage()
|
||||
{
|
||||
NetworkObjectId = NetworkObjectId,
|
||||
NetworkBehaviourId = NetworkBehaviourId,
|
||||
State = m_LocalAuthoritativeNetworkState
|
||||
};
|
||||
|
||||
// Determine what network delivery method to use:
|
||||
// When to send reliable packets:
|
||||
@@ -3259,32 +3215,32 @@ namespace Unity.Netcode.Components
|
||||
| m_LocalAuthoritativeNetworkState.UnreliableFrameSync | m_LocalAuthoritativeNetworkState.SynchronizeBaseHalfFloat
|
||||
? NetworkDelivery.ReliableSequenced : NetworkDelivery.UnreliableSequenced;
|
||||
|
||||
using (writer)
|
||||
// Server-host always sends updates to all clients (but itself)
|
||||
if (IsServer)
|
||||
{
|
||||
writer.WriteNetworkSerializable(m_LocalAuthoritativeNetworkState);
|
||||
// Server-host always sends updates to all clients (but itself)
|
||||
if (IsServer)
|
||||
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
{
|
||||
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
|
||||
if (NetworkManager.ServerClientId == clientId)
|
||||
{
|
||||
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
|
||||
if (NetworkManager.ServerClientId == clientId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
customMessageManager.SendNamedMessage(m_MessageName, clientId, writer, networkDelivery);
|
||||
continue;
|
||||
}
|
||||
if (!NetworkObject.Observers.Contains(clientId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
NetworkManager.MessageManager.SendMessage(ref networkTransformMessage, networkDelivery, clientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clients (owner authoritative) send messages to the server-host
|
||||
customMessageManager.SendNamedMessage(m_MessageName, NetworkManager.ServerClientId, writer, networkDelivery);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clients (owner authoritative) send messages to the server-host
|
||||
NetworkManager.MessageManager.SendMessage(ref networkTransformMessage, networkDelivery, NetworkManager.ServerClientId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Network Tick Registration and Handling
|
||||
private static Dictionary<NetworkManager, NetworkTransformTickRegistration> s_NetworkTickRegistration = new Dictionary<NetworkManager, NetworkTransformTickRegistration>();
|
||||
|
||||
private static void RemoveTickUpdate(NetworkManager networkManager)
|
||||
@@ -3379,7 +3335,7 @@ namespace Unity.Netcode.Components
|
||||
|
||||
/// <summary>
|
||||
/// If a NetworkTransformTickRegistration exists for the NetworkManager instance, then this will
|
||||
/// remove the NetworkTransform instance from the single tick update entry point.
|
||||
/// remove the NetworkTransform instance from the single tick update entry point.
|
||||
/// </summary>
|
||||
/// <param name="networkTransform"></param>
|
||||
private static void DeregisterForTickUpdate(NetworkTransform networkTransform)
|
||||
@@ -3394,6 +3350,8 @@ namespace Unity.Netcode.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal interface INetworkTransformLogStateEntry
|
||||
|
||||
Reference in New Issue
Block a user