com.unity.netcode.gameobjects@2.0.0-exp.4

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).

## [2.0.0-exp.4] - 2024-05-31

### Added

- Added `NetworkRigidbodyBase.AttachToFixedJoint` and `NetworkRigidbodyBase.DetachFromFixedJoint` to replace parenting for rigid bodies that have `NetworkRigidbodyBase.UseRigidBodyForMotion` enabled. (#2933)
- Added `NetworkBehaviour.OnNetworkPreSpawn` and `NetworkBehaviour.OnNetworkPostSpawn` methods that provide the ability to handle pre and post spawning actions during the `NetworkObject` spawn sequence. (#2912)
- Added a client-side only `NetworkBehaviour.OnNetworkSessionSynchronized` convenience method that is invoked on all `NetworkBehaviour`s after a newly joined client has finished synchronizing with the network session in progress. (#2912)
- Added `NetworkBehaviour.OnInSceneObjectsSpawned` convenience method that is invoked when all in-scene `NetworkObject`s have been spawned after a scene has been loaded or upon a host or server starting. (#2912)

### Fixed

- Fixed issue where non-authoritative rigid bodies with `NetworkRigidbodyBase.UseRigidBodyForMotion` enabled would constantly log errors about the renderTime being before `StartTimeConsumed`. (#2933)
- Fixed issue where in-scene placed NetworkObjects could be destroyed if a client disconnects early and/or before approval. (#2924)
- Fixed issue where a `NetworkObject` component's associated `NetworkBehaviour` components would not be detected if scene loading is disabled in the editor and the currently loaded scene has in-scene placed `NetworkObject`s. (#2912)
- Fixed issue where an in-scene placed `NetworkObject` with `NetworkTransform` that is also parented under a `GameObject` would not properly synchronize when the parent `GameObject` had a world space position other than 0,0,0. (#2898)

### Changed

- Change all the access modifiers of test class from Public to Internal (#2930)
- Changed messages are now sorted by enum values as opposed to ordinally sorting the messages by their type name. (#2929)
- Changed `NetworkClient.SessionModeTypes` to `NetworkClient.NetworkTopologyTypes`. (#2875)
- Changed `NetworkClient.SessionModeType` to `NetworkClient.NetworkTopologyType`. (#2875)
- Changed `NetworkConfig.SessionMode` to `NeworkConfig.NetworkTopology`. (#2875)
This commit is contained in:
Unity Technologies
2024-05-31 00:00:00 +00:00
parent 143a6cbd34
commit 63c7e4c78a
177 changed files with 1792 additions and 820 deletions

View File

@@ -660,16 +660,69 @@ namespace Unity.Netcode
/// <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) { }
/// 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)
/// </summary>
/// <remarks>
/// <param name="networkManager">a ref to the <see cref="NetworkManager"/> since this is not yet set on the <see cref="NetworkBehaviour"/></param>
/// The <see cref="NetworkBehaviour"/> will not have anything assigned to it at this point in time.
/// Settings like ownership, NetworkBehaviourId, NetworkManager, and most other spawn related properties will not be set.
/// This can be used to handle things like initializing/instantiating a NetworkVariable or the like.
/// </remarks>
protected virtual void OnNetworkPreSpawn(ref NetworkManager networkManager) { }
/// <summary>
/// Gets called when the <see cref="NetworkObject"/> gets spawned, message handlers are ready to be registered and the network is setup.
/// </summary>
public virtual void OnNetworkSpawn() { }
/// <summary>
/// Gets called after the <see cref="NetworkObject"/> is spawned. All NetworkBehaviours associated with the NetworkObject will have had <see cref="OnNetworkSpawn"/> invoked.
/// </summary>
/// <remarks>
/// Will be invoked on each <see cref="NetworkBehaviour"/> associated with the <see cref="NetworkObject"/> being spawned.
/// All associated <see cref="NetworkBehaviour"/> components will have had <see cref="OnNetworkSpawn"/> invoked on the spawned <see cref="NetworkObject"/>.
/// </remarks>
protected virtual void OnNetworkPostSpawn() { }
/// <summary>
/// [Client-Side Only]
/// When a new client joins it is synchronized with all spawned NetworkObjects and scenes loaded for the session joined. At the end of the synchronization process, when all
/// <see cref="NetworkObject"/>s and scenes (if scene management is enabled) have finished synchronizing, all NetworkBehaviour components associated with spawned <see cref="NetworkObject"/>s
/// will have this method invoked.
/// </summary>
/// <remarks>
/// This can be used to handle post synchronization actions where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
/// This is only invoked on clients during a client-server network topology session.
/// </remarks>
protected virtual void OnNetworkSessionSynchronized() { }
/// <summary>
/// [Client & Server Side]
/// When a scene is loaded an in-scene placed NetworkObjects are all spawned, this method is invoked on all of the newly spawned in-scene placed NetworkObjects.
/// </summary>
/// <remarks>
/// This can be used to handle post scene loaded actions for in-scene placed NetworkObjcts where you might need to access a different NetworkObject and/or NetworkBehaviour not local to the current NetworkObject context.
/// </remarks>
protected virtual void OnInSceneObjectsSpawned() { }
/// <summary>
/// Gets called when the <see cref="NetworkObject"/> gets despawned. Is called both on the server and clients.
/// </summary>
public virtual void OnNetworkDespawn() { }
internal void NetworkPreSpawn(ref NetworkManager networkManager)
{
try
{
OnNetworkPreSpawn(ref networkManager);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
internal void InternalOnNetworkSpawn()
{
IsSpawned = true;
@@ -699,6 +752,42 @@ namespace Unity.Netcode
}
}
internal void NetworkPostSpawn()
{
try
{
OnNetworkPostSpawn();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
internal void NetworkSessionSynchronized()
{
try
{
OnNetworkSessionSynchronized();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
internal void InSceneNetworkObjectsSpawned()
{
try
{
OnInSceneObjectsSpawned();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
internal void InternalOnNetworkDespawn()
{
IsSpawned = false;

View File

@@ -8,6 +8,7 @@ using UnityEditor;
#endif
using UnityEngine.SceneManagement;
using Debug = UnityEngine.Debug;
using Unity.Netcode.Components;
namespace Unity.Netcode
{
@@ -43,7 +44,7 @@ namespace Unity.Netcode
{
get
{
return NetworkConfig.SessionMode == SessionModeTypes.DistributedAuthority;
return NetworkConfig.NetworkTopology == NetworkTopologyTypes.DistributedAuthority;
}
}
@@ -177,6 +178,45 @@ namespace Unity.Netcode
}
}
internal Dictionary<ulong, NetworkTransform> NetworkTransformUpdate = new Dictionary<ulong, NetworkTransform>();
#if COM_UNITY_MODULES_PHYSICS
internal Dictionary<ulong, NetworkTransform> NetworkTransformFixedUpdate = new Dictionary<ulong, NetworkTransform>();
#endif
internal void NetworkTransformRegistration(NetworkTransform networkTransform, bool forUpdate = true, bool register = true)
{
if (forUpdate)
{
if (register)
{
if (!NetworkTransformUpdate.ContainsKey(networkTransform.NetworkObjectId))
{
NetworkTransformUpdate.Add(networkTransform.NetworkObjectId, networkTransform);
}
}
else
{
NetworkTransformUpdate.Remove(networkTransform.NetworkObjectId);
}
}
#if COM_UNITY_MODULES_PHYSICS
else
{
if (register)
{
if (!NetworkTransformFixedUpdate.ContainsKey(networkTransform.NetworkObjectId))
{
NetworkTransformFixedUpdate.Add(networkTransform.NetworkObjectId, networkTransform);
}
}
else
{
NetworkTransformFixedUpdate.Remove(networkTransform.NetworkObjectId);
}
}
#endif
}
public void NetworkUpdate(NetworkUpdateStage updateStage)
{
switch (updateStage)
@@ -192,11 +232,36 @@ namespace Unity.Netcode
MessageManager.CleanupDisconnectedClients();
}
break;
#if COM_UNITY_MODULES_PHYSICS
case NetworkUpdateStage.FixedUpdate:
{
foreach (var networkTransformEntry in NetworkTransformFixedUpdate)
{
if (networkTransformEntry.Value.gameObject.activeInHierarchy && networkTransformEntry.Value.IsSpawned)
{
networkTransformEntry.Value.OnFixedUpdate();
}
}
}
break;
#endif
case NetworkUpdateStage.PreUpdate:
{
NetworkTimeSystem.UpdateTime();
}
break;
case NetworkUpdateStage.PreLateUpdate:
{
// Non-physics based non-authority NetworkTransforms update their states after all other components
foreach (var networkTransformEntry in NetworkTransformUpdate)
{
if (networkTransformEntry.Value.gameObject.activeInHierarchy && networkTransformEntry.Value.IsSpawned)
{
networkTransformEntry.Value.OnUpdate();
}
}
}
break;
case NetworkUpdateStage.PostLateUpdate:
{
// Handle deferred despawning
@@ -942,6 +1007,10 @@ namespace Unity.Netcode
internal void Initialize(bool server)
{
#if COM_UNITY_MODULES_PHYSICS
NetworkTransformFixedUpdate.Clear();
#endif
NetworkTransformUpdate.Clear();
//DANGOEXP TODO: Remove this before finalizing the experimental release
NetworkConfig.AutoSpawnPlayerPrefabClientSide = DistributedAuthorityMode;
@@ -978,7 +1047,11 @@ namespace Unity.Netcode
}
this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate);
#if COM_UNITY_MODULES_PHYSICS
this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate);
#endif
this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate);
this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate);
this.RegisterNetworkUpdate(NetworkUpdateStage.PostLateUpdate);
// ComponentFactory needs to set its defaults next
@@ -994,11 +1067,17 @@ namespace Unity.Netcode
MessageManager.Hook(new NetworkManagerHooks(this));
#if DEVELOPMENT_BUILD || UNITY_EDITOR
MessageManager.Hook(new ProfilingHooks());
if (NetworkConfig.NetworkProfilingMetrics)
{
MessageManager.Hook(new ProfilingHooks());
}
#endif
#if MULTIPLAYER_TOOLS
MessageManager.Hook(new MetricHooks(this));
if (NetworkConfig.NetworkMessageMetrics)
{
MessageManager.Hook(new MetricHooks(this));
}
#endif
// Assures there is a server message queue available

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Unity.Netcode.Components;
#if UNITY_EDITOR
using UnityEditor;
#if UNITY_2021_2_OR_NEWER
@@ -14,6 +15,7 @@ using UnityEngine;
using UnityEngine.SceneManagement;
namespace Unity.Netcode
{
/// <summary>
@@ -55,6 +57,34 @@ namespace Unity.Netcode
}
}
/// <summary>
/// All <see cref="NetworkTransform"></see> component instances associated with a <see cref="NetworkObject"/> component instance.
/// </summary>
/// <remarks>
/// When parented, all child <see cref="NetworkTransform"/> component instances under a <see cref="NetworkObject"/> component instance that do not have
/// another <see cref="NetworkObject"/> component instance will be associated with the initial component instance. This list does not contain any parented
/// children <see cref="NetworkObject"/> instances with one or more <see cref="NetworkTransform"/> component instance(s).
/// </remarks>
public List<NetworkTransform> NetworkTransforms { get; private set; }
#if COM_UNITY_MODULES_PHYSICS
/// <summary>
/// All <see cref="NetworkRigidbodyBase"></see> component instances associated with a <see cref="NetworkObject"/> component instance.
/// NOTE: This is only available if a physics package is included. If not, then this will not be available!
/// </summary>
/// <remarks>
/// When parented, all child <see cref="NetworkRigidbodyBase"/> component instances under a <see cref="NetworkObject"/> component instance that do not have
/// another <see cref="NetworkObject"/> component instance will be associated with the initial component instance. This list does not contain any parented
/// child <see cref="NetworkObject"/> instances with one or more <see cref="NetworkTransform"/> component instance(s).
/// </remarks>
public List<NetworkRigidbodyBase> NetworkRigidbodies { get; private set; }
#endif
/// <summary>
/// The current parent <see cref="NetworkObject"/> component instance to this <see cref="NetworkObject"/> component instance. When there is no parent then
/// this will be <see cref="null"/>.
/// </summary>
public NetworkObject CurrentParent { get; private set; }
#if UNITY_EDITOR
private const string k_GlobalIdTemplate = "GlobalObjectId_V1-{0}-{1}-{2}-{3}";
@@ -398,8 +428,11 @@ namespace Unity.Netcode
/// <summary>
/// Determines whether a NetworkObject can be distributed to other clients during
/// a <see cref="SessionModeTypes.DistributedAuthority"/> session.
/// a <see cref="NetworkTopologyTypes.DistributedAuthority"/> session.
/// </summary>
#if !MULTIPLAYER_SDK_INSTALLED
[HideInInspector]
#endif
[SerializeField]
internal OwnershipStatus Ownership = OwnershipStatus.Distributable;
@@ -1894,7 +1927,6 @@ namespace Unity.Netcode
internal bool InternalTrySetParent(NetworkObject parent, bool worldPositionStays = true)
{
if (parent != null && (IsSpawned ^ parent.IsSpawned))
{
if (NetworkManager != null && !NetworkManager.ShutdownInProgress)
@@ -1907,10 +1939,12 @@ namespace Unity.Netcode
if (parent == null)
{
CurrentParent = null;
transform.SetParent(null, worldPositionStays);
}
else
{
CurrentParent = parent;
transform.SetParent(parent.transform, worldPositionStays);
}
@@ -2209,6 +2243,18 @@ namespace Unity.Netcode
}
}
internal void InvokeBehaviourNetworkPreSpawn()
{
var networkManager = NetworkManager;
for (int i = 0; i < ChildNetworkBehaviours.Count; i++)
{
if (ChildNetworkBehaviours[i].gameObject.activeInHierarchy)
{
ChildNetworkBehaviours[i].NetworkPreSpawn(ref networkManager);
}
}
}
internal void InvokeBehaviourNetworkSpawn()
{
NetworkManager.SpawnManager.UpdateOwnershipTable(this, OwnerClientId);
@@ -2238,6 +2284,42 @@ namespace Unity.Netcode
}
}
internal void InvokeBehaviourNetworkPostSpawn()
{
for (int i = 0; i < ChildNetworkBehaviours.Count; i++)
{
if (ChildNetworkBehaviours[i].gameObject.activeInHierarchy)
{
ChildNetworkBehaviours[i].NetworkPostSpawn();
}
}
}
internal void InternalNetworkSessionSynchronized()
{
for (int i = 0; i < ChildNetworkBehaviours.Count; i++)
{
if (ChildNetworkBehaviours[i].gameObject.activeInHierarchy)
{
ChildNetworkBehaviours[i].NetworkSessionSynchronized();
}
}
}
internal void InternalInSceneNetworkObjectsSpawned()
{
for (int i = 0; i < ChildNetworkBehaviours.Count; i++)
{
if (ChildNetworkBehaviours[i].gameObject.activeInHierarchy)
{
ChildNetworkBehaviours[i].InSceneNetworkObjectsSpawned();
}
}
}
internal void InvokeBehaviourNetworkDespawn()
{
NetworkManager.SpawnManager.UpdateOwnershipTable(this, OwnerClientId, true);
@@ -2271,6 +2353,25 @@ namespace Unity.Netcode
if (networkBehaviours[i].NetworkObject == this)
{
m_ChildNetworkBehaviours.Add(networkBehaviours[i]);
var type = networkBehaviours[i].GetType();
if (type.IsInstanceOfType(typeof(NetworkTransform)) || type.IsSubclassOf(typeof(NetworkTransform)))
{
if (NetworkTransforms == null)
{
NetworkTransforms = new List<NetworkTransform>();
}
NetworkTransforms.Add(networkBehaviours[i] as NetworkTransform);
}
#if COM_UNITY_MODULES_PHYSICS
else if (type.IsSubclassOf(typeof(NetworkRigidbodyBase)))
{
if (NetworkRigidbodies == null)
{
NetworkRigidbodies = new List<NetworkRigidbodyBase>();
}
NetworkRigidbodies.Add(networkBehaviours[i] as NetworkRigidbodyBase);
}
#endif
}
}
@@ -2862,6 +2963,9 @@ namespace Unity.Netcode
// in order to be able to determine which NetworkVariables the client will be allowed to read.
networkObject.OwnerClientId = sceneObject.OwnerClientId;
// Special Case: Invoke NetworkBehaviour.OnPreSpawn methods here before SynchronizeNetworkBehaviours
networkObject.InvokeBehaviourNetworkPreSpawn();
// Synchronize NetworkBehaviours
var bufferSerializer = new BufferSerializer<BufferSerializerReader>(new BufferSerializerReader(reader));
networkObject.SynchronizeNetworkBehaviours(ref bufferSerializer, networkManager.LocalClientId);
@@ -3051,6 +3155,11 @@ namespace Unity.Netcode
private void Awake()
{
m_ChildNetworkBehaviours = null;
NetworkTransforms?.Clear();
#if COM_UNITY_MODULES_PHYSICS
NetworkRigidbodies?.Clear();
#endif
SetCachedParent(transform.parent);
SceneOrigin = gameObject.scene;
}