com.unity.netcode.gameobjects@1.5.2
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.5.2] - 2023-07-24 ### Added ### Fixed - Fixed issue where `NetworkClient.OwnedObjects` was not returning any owned objects due to the `NetworkClient.IsConnected` not being properly set. (#2631) - Fixed a crash when calling TrySetParent with a null Transform (#2625) - Fixed issue where a `NetworkTransform` using full precision state updates was losing transform state updates when interpolation was enabled. (#2624) - Fixed issue where `NetworkObject.SpawnWithObservers` was not being honored for late joining clients. (#2623) - Fixed issue where invoking `NetworkManager.Shutdown` multiple times, depending upon the timing, could cause an exception. (#2622) - Fixed issue where removing ownership would not notify the server that it gained ownership. This also resolves the issue where an owner authoritative NetworkTransform would not properly initialize upon removing ownership from a remote client. (#2618) - Fixed ILPP issues when using CoreCLR and for certain dedicated server builds. (#2614) - Fixed an ILPP compile error when creating a generic NetworkBehaviour singleton with a static T instance. (#2603) ### Changed
This commit is contained in:
@@ -36,15 +36,11 @@ namespace Unity.Netcode
|
||||
/// <summary>
|
||||
/// The ClientId of the NetworkClient
|
||||
/// </summary>
|
||||
// TODO-2023-Q2: Determine if we want to make this property a public get and internal/private set
|
||||
// There is no reason for a user to want to set this, but this will fail the package-validation-suite
|
||||
public ulong ClientId;
|
||||
|
||||
/// <summary>
|
||||
/// The PlayerObject of the Client
|
||||
/// </summary>
|
||||
// TODO-2023-Q2: Determine if we want to make this property a public get and internal/private set
|
||||
// There is no reason for a user to want to set this, but this will fail the package-validation-suite
|
||||
public NetworkObject PlayerObject;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Unity.Netcode
|
||||
/// - Processing <see cref="NetworkEvent"/>s.
|
||||
/// - Client Disconnection
|
||||
/// </summary>
|
||||
// TODO 2023-Q2: Discuss what kind of public API exposure we want for this
|
||||
public sealed class NetworkConnectionManager
|
||||
{
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
@@ -628,6 +627,8 @@ namespace Unity.Netcode
|
||||
};
|
||||
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
|
||||
{
|
||||
// Update the observed spawned NetworkObjects for the newly connected player when scene management is disabled
|
||||
NetworkManager.SpawnManager.UpdateObservedNetworkObjects(ownerClientId);
|
||||
if (NetworkManager.SpawnManager.SpawnedObjectsList.Count != 0)
|
||||
{
|
||||
message.SpawnedObjectsList = NetworkManager.SpawnManager.SpawnedObjectsList;
|
||||
@@ -651,12 +652,13 @@ namespace Unity.Netcode
|
||||
SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, ownerClientId);
|
||||
message.MessageVersions.Dispose();
|
||||
|
||||
// If scene management is enabled, then let NetworkSceneManager handle the initial scene and NetworkObject synchronization
|
||||
// If scene management is disabled, then we are done and notify the local host-server the client is connected
|
||||
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
|
||||
{
|
||||
NetworkManager.ConnectedClients[ownerClientId].IsConnected = true;
|
||||
InvokeOnClientConnectedCallback(ownerClientId);
|
||||
}
|
||||
else
|
||||
else // Otherwise, let NetworkSceneManager handle the initial scene and NetworkObject synchronization
|
||||
{
|
||||
NetworkManager.SceneManager.SynchronizeNetworkObjects(ownerClientId);
|
||||
}
|
||||
@@ -665,6 +667,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
LocalClient = client;
|
||||
NetworkManager.SpawnManager.UpdateObservedNetworkObjects(ownerClientId);
|
||||
LocalClient.IsConnected = true;
|
||||
}
|
||||
|
||||
if (!response.CreatePlayerObject || (response.PlayerPrefabHash == null && NetworkManager.NetworkConfig.PlayerPrefab == null))
|
||||
@@ -730,12 +733,10 @@ namespace Unity.Netcode
|
||||
internal NetworkClient AddClient(ulong clientId)
|
||||
{
|
||||
var networkClient = LocalClient;
|
||||
if (clientId != NetworkManager.ServerClientId)
|
||||
{
|
||||
networkClient = new NetworkClient();
|
||||
networkClient.SetRole(isServer: false, isClient: true, NetworkManager);
|
||||
networkClient.ClientId = clientId;
|
||||
}
|
||||
|
||||
networkClient = new NetworkClient();
|
||||
networkClient.SetRole(clientId == NetworkManager.ServerClientId, isClient: true, NetworkManager);
|
||||
networkClient.ClientId = clientId;
|
||||
|
||||
ConnectedClients.Add(clientId, networkClient);
|
||||
ConnectedClientsList.Add(networkClient);
|
||||
@@ -798,8 +799,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle changing ownership and prefab handlers
|
||||
// TODO-2023: Look into whether in-scene placed NetworkObjects could be destroyed if ownership changes to a client
|
||||
// Handle changing ownership and prefab handlers
|
||||
for (int i = clientOwnedObjects.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var ownedObject = clientOwnedObjects[i];
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace Unity.Netcode
|
||||
Server = 1,
|
||||
Client = 2
|
||||
}
|
||||
|
||||
|
||||
// NetworkBehaviourILPP will override this in derived classes to return the name of the concrete type
|
||||
internal virtual string __getTypeName() => nameof(NetworkBehaviour);
|
||||
|
||||
@@ -98,7 +96,6 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
@@ -230,7 +227,6 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Unity.Netcode
|
||||
m_NetworkManager.NetworkTickSystem.Tick -= NetworkBehaviourUpdater_Tick;
|
||||
}
|
||||
|
||||
// TODO 2023-Q2: Order of operations requires NetworkVariable updates first then showing NetworkObjects
|
||||
// Order of operations requires NetworkVariable updates first then showing NetworkObjects
|
||||
private void NetworkBehaviourUpdater_Tick()
|
||||
{
|
||||
// First update NetworkVariables
|
||||
|
||||
@@ -59,13 +59,12 @@ namespace Unity.Netcode
|
||||
// Metrics update needs to be driven by NetworkConnectionManager's update to assure metrics are dispatched after the send queue is processed.
|
||||
MetricsManager.UpdateMetrics();
|
||||
|
||||
// TODO 2023-Q2: Determine a better way to handle this
|
||||
// TODO: Determine a better way to handle this
|
||||
NetworkObject.VerifyParentingStatus();
|
||||
|
||||
// This is "ok" to invoke when not processing messages since it is just cleaning up messages that never got handled within their timeout period.
|
||||
DeferredMessageManager.CleanupStaleTriggers();
|
||||
|
||||
// TODO 2023-Q2: Determine a better way to handle this
|
||||
if (m_ShuttingDown)
|
||||
{
|
||||
ShutdownInternal();
|
||||
@@ -834,9 +833,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
ConnectionManager.LocalClient.SetRole(true, true, this);
|
||||
|
||||
Initialize(true);
|
||||
|
||||
try
|
||||
{
|
||||
IsListening = NetworkConfig.NetworkTransport.StartServer();
|
||||
@@ -942,10 +939,16 @@ namespace Unity.Netcode
|
||||
if (IsServer || IsClient)
|
||||
{
|
||||
m_ShuttingDown = true;
|
||||
MessageManager.StopProcessing = discardMessageQueue;
|
||||
if (MessageManager != null)
|
||||
{
|
||||
MessageManager.StopProcessing = discardMessageQueue;
|
||||
}
|
||||
}
|
||||
|
||||
NetworkConfig.NetworkTransport.OnTransportEvent -= ConnectionManager.HandleNetworkEvent;
|
||||
if (NetworkConfig != null && NetworkConfig.NetworkTransport != null)
|
||||
{
|
||||
NetworkConfig.NetworkTransport.OnTransportEvent -= ConnectionManager.HandleNetworkEvent;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures that the NetworkManager is cleaned up before OnDestroy is run on NetworkObjects and NetworkBehaviours when unloading a scene with a NetworkManager
|
||||
@@ -1029,6 +1032,8 @@ namespace Unity.Netcode
|
||||
// Ensures that the NetworkManager is cleaned up before OnDestroy is run on NetworkObjects and NetworkBehaviours when quitting the application.
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
// Make sure ShutdownInProgress returns true during this time
|
||||
m_ShuttingDown = true;
|
||||
OnDestroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -733,6 +733,12 @@ namespace Unity.Netcode
|
||||
/// <returns>Whether or not reparenting was successful.</returns>
|
||||
public bool TrySetParent(Transform parent, bool worldPositionStays = true)
|
||||
{
|
||||
// If we are removing ourself from a parent
|
||||
if (parent == null)
|
||||
{
|
||||
return TrySetParent((NetworkObject)null, worldPositionStays);
|
||||
}
|
||||
|
||||
var networkObject = parent.GetComponent<NetworkObject>();
|
||||
|
||||
// If the parent doesn't have a NetworkObjet then return false, otherwise continue trying to parent
|
||||
@@ -1192,7 +1198,6 @@ namespace Unity.Netcode
|
||||
{
|
||||
NetworkLog.LogError($"{nameof(NetworkBehaviour)} index {index} was out of bounds for {name}. NetworkBehaviours must be the same, and in the same order, between server and client.");
|
||||
}
|
||||
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
var currentKnownChildren = new System.Text.StringBuilder();
|
||||
@@ -1205,7 +1210,6 @@ namespace Unity.Netcode
|
||||
}
|
||||
NetworkLog.LogInfo(currentKnownChildren.ToString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ namespace Unity.Netcode
|
||||
{
|
||||
networkVariable.WriteDelta(writer);
|
||||
}
|
||||
|
||||
NetworkBehaviour.NetworkManager.NetworkMetrics.TrackNetworkVariableDeltaSent(
|
||||
TargetClientId,
|
||||
NetworkBehaviour.NetworkObject,
|
||||
@@ -207,7 +206,6 @@ namespace Unity.Netcode
|
||||
networkBehaviour.__getTypeName(),
|
||||
context.MessageSize);
|
||||
|
||||
|
||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
{
|
||||
if (m_ReceivedNetworkVariableData.Position > (readStartPos + varSize))
|
||||
|
||||
@@ -72,6 +72,14 @@ namespace Unity.Netcode
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(new Exception("Unhandled RPC exception!", ex));
|
||||
if (networkManager.LogLevel == LogLevel.Developer)
|
||||
{
|
||||
Debug.Log($"RPC Table Contents");
|
||||
foreach (var entry in NetworkManager.__rpc_func_table)
|
||||
{
|
||||
Debug.Log($"{entry.Key} | {entry.Value.Method.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2191,6 +2191,10 @@ namespace Unity.Netcode
|
||||
ClientId = clientId
|
||||
});
|
||||
|
||||
// At this point the client is considered fully "connected"
|
||||
NetworkManager.ConnectedClients[clientId].IsConnected = true;
|
||||
|
||||
// All scenes are synchronized, let the server know we are done synchronizing
|
||||
OnSynchronizeComplete?.Invoke(clientId);
|
||||
|
||||
// At this time the client is fully synchronized with all loaded scenes and
|
||||
|
||||
@@ -113,12 +113,6 @@ namespace Unity.Netcode
|
||||
// Remove the previous owner's entry
|
||||
OwnershipToObjectsTable[previousOwner].Remove(networkObject.NetworkObjectId);
|
||||
|
||||
// Server or Host alway invokes the lost ownership notification locally
|
||||
if (NetworkManager.IsServer)
|
||||
{
|
||||
networkObject.InvokeBehaviourOnLostOwnership();
|
||||
}
|
||||
|
||||
// If we are removing the entry (i.e. despawning or client lost ownership)
|
||||
if (isRemoving)
|
||||
{
|
||||
@@ -143,12 +137,6 @@ namespace Unity.Netcode
|
||||
{
|
||||
// Add the new ownership entry
|
||||
OwnershipToObjectsTable[newOwner].Add(networkObject.NetworkObjectId, networkObject);
|
||||
|
||||
// Server or Host always invokes the gained ownership notification locally
|
||||
if (NetworkManager.IsServer)
|
||||
{
|
||||
networkObject.InvokeBehaviourOnGainedOwnership();
|
||||
}
|
||||
}
|
||||
else if (isRemoving)
|
||||
{
|
||||
@@ -227,43 +215,6 @@ namespace Unity.Netcode
|
||||
return null;
|
||||
}
|
||||
|
||||
internal void RemoveOwnership(NetworkObject networkObject)
|
||||
{
|
||||
if (!NetworkManager.IsServer)
|
||||
{
|
||||
throw new NotServerException("Only the server can change ownership");
|
||||
}
|
||||
|
||||
if (!networkObject.IsSpawned)
|
||||
{
|
||||
throw new SpawnStateException("Object is not spawned");
|
||||
}
|
||||
|
||||
// If we made it here then we are the server and if the server is determined to already be the owner
|
||||
// then ignore the RemoveOwnership invocation.
|
||||
if (networkObject.OwnerClientId == NetworkManager.ServerClientId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
networkObject.OwnerClientId = NetworkManager.ServerClientId;
|
||||
|
||||
// Server removes the entry and takes over ownership before notifying
|
||||
UpdateOwnershipTable(networkObject, NetworkManager.ServerClientId, true);
|
||||
|
||||
var message = new ChangeOwnershipMessage
|
||||
{
|
||||
NetworkObjectId = networkObject.NetworkObjectId,
|
||||
OwnerClientId = networkObject.OwnerClientId
|
||||
};
|
||||
var size = NetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, NetworkManager.ConnectedClientsIds);
|
||||
|
||||
foreach (var client in NetworkManager.ConnectedClients)
|
||||
{
|
||||
NetworkManager.NetworkMetrics.TrackOwnershipChangeSent(client.Key, networkObject, size);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to get a network client for a clientId from the NetworkManager.
|
||||
/// On the server this will check the <see cref="NetworkManager.ConnectedClients"/> list.
|
||||
@@ -289,6 +240,11 @@ namespace Unity.Netcode
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void RemoveOwnership(NetworkObject networkObject)
|
||||
{
|
||||
ChangeOwnership(networkObject, NetworkManager.ServerClientId);
|
||||
}
|
||||
|
||||
internal void ChangeOwnership(NetworkObject networkObject, ulong clientId)
|
||||
{
|
||||
if (!NetworkManager.IsServer)
|
||||
@@ -301,14 +257,21 @@ namespace Unity.Netcode
|
||||
throw new SpawnStateException("Object is not spawned");
|
||||
}
|
||||
|
||||
// Assign the new owner
|
||||
networkObject.OwnerClientId = clientId;
|
||||
|
||||
// Always notify locally on the server when ownership is lost
|
||||
networkObject.InvokeBehaviourOnLostOwnership();
|
||||
|
||||
networkObject.MarkVariablesDirty(true);
|
||||
NetworkManager.BehaviourUpdater.AddForUpdate(networkObject);
|
||||
|
||||
// Server adds entries for all client ownership
|
||||
UpdateOwnershipTable(networkObject, networkObject.OwnerClientId);
|
||||
|
||||
// Always notify locally on the server when a new owner is assigned
|
||||
networkObject.InvokeBehaviourOnGainedOwnership();
|
||||
|
||||
var message = new ChangeOwnershipMessage
|
||||
{
|
||||
NetworkObjectId = networkObject.NetworkObjectId,
|
||||
@@ -952,27 +915,35 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all spawned <see cref="NetworkObject.Observers"/> for the specified client
|
||||
/// Updates all spawned <see cref="NetworkObject.Observers"/> for the specified newly connected client
|
||||
/// Note: if the clientId is the server then it is observable to all spawned <see cref="NetworkObject"/>'s
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is to only to be used for newly connected clients in order to update the observers list for
|
||||
/// each NetworkObject instance.
|
||||
/// </remarks>
|
||||
internal void UpdateObservedNetworkObjects(ulong clientId)
|
||||
{
|
||||
foreach (var sobj in SpawnedObjectsList)
|
||||
{
|
||||
// If the NetworkObject has no visibility check then prepare to add this client as an observer
|
||||
if (sobj.CheckObjectVisibility == null)
|
||||
{
|
||||
if (!sobj.Observers.Contains(clientId))
|
||||
// If the client is not part of the observers and spawn with observers is enabled on this instance or the clientId is the server
|
||||
if (!sobj.Observers.Contains(clientId) && (sobj.SpawnWithObservers || clientId == NetworkManager.ServerClientId))
|
||||
{
|
||||
sobj.Observers.Add(clientId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// CheckObject visibility overrides SpawnWithObservers under this condition
|
||||
if (sobj.CheckObjectVisibility(clientId))
|
||||
{
|
||||
sobj.Observers.Add(clientId);
|
||||
}
|
||||
else if (sobj.Observers.Contains(clientId))
|
||||
else // Otherwise, if the observers contains the clientId (shouldn't happen) then remove it since CheckObjectVisibility returned false
|
||||
if (sobj.Observers.Contains(clientId))
|
||||
{
|
||||
sobj.Observers.Remove(clientId);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ namespace Unity.Netcode
|
||||
/// </summary>
|
||||
public class NetworkTimeSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO 2023-Q2: Not sure if this just needs to go away, but there is nothing that ever replaces this
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This was the original comment when it lived in NetworkManager:
|
||||
/// todo talk with UX/Product, find good default value for this
|
||||
|
||||
Reference in New Issue
Block a user