com.unity.netcode.gameobjects@1.0.0-pre.7
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.0.0-pre.7] - 2022-04-01 ### Added - Added editor only check prior to entering into play mode if the currently open and active scene is in the build list and if not displays a dialog box asking the user if they would like to automatically add it prior to entering into play mode. (#1828) - Added `UnityTransport` implementation and `com.unity.transport` package dependency (#1823) - Added `NetworkVariableWritePermission` to `NetworkVariableBase` and implemented `Owner` client writable netvars. (#1762) - `UnityTransport` settings can now be set programmatically. (#1845) - `FastBufferWriter` and Reader IsInitialized property. (#1859) ### Changed - Updated `UnityTransport` dependency on `com.unity.transport` to 1.0.0 (#1849) ### Removed - Removed `SnapshotSystem` (#1852) - Removed `com.unity.modules.animation`, `com.unity.modules.physics` and `com.unity.modules.physics2d` dependencies from the package (#1812) - Removed `com.unity.collections` dependency from the package (#1849) ### Fixed - Fixed in-scene placed NetworkObjects not being found/ignored after a client disconnects and then reconnects. (#1850) - Fixed issue where `UnityTransport` send queues were not flushed when calling `DisconnectLocalClient` or `DisconnectRemoteClient`. (#1847) - Fixed NetworkBehaviour dependency verification check for an existing NetworkObject not searching from root parent transform relative GameObject. (#1841) - Fixed issue where entries were not being removed from the NetworkSpawnManager.OwnershipToObjectsTable. (#1838) - Fixed ClientRpcs would always send to all connected clients by default as opposed to only sending to the NetworkObject's Observers list by default. (#1836) - Fixed clarity for NetworkSceneManager client side notification when it receives a scene hash value that does not exist in its local hash table. (#1828) - Fixed client throws a key not found exception when it times out using UNet or UTP. (#1821) - Fixed network variable updates are no longer limited to 32,768 bytes when NetworkConfig.EnsureNetworkVariableLengthSafety is enabled. The limits are now determined by what the transport can send in a message. (#1811) - Fixed in-scene NetworkObjects get destroyed if a client fails to connect and shuts down the NetworkManager. (#1809) - Fixed user never being notified in the editor that a NetworkBehaviour requires a NetworkObject to function properly. (#1808) - Fixed PlayerObjects and dynamically spawned NetworkObjects not being added to the NetworkClient's OwnedObjects (#1801) - Fixed issue where NetworkManager would continue starting even if the NetworkTransport selected failed. (#1780) - Fixed issue when spawning new player if an already existing player exists it does not remove IsPlayer from the previous player (#1779) - Fixed lack of notification that NetworkManager and NetworkObject cannot be added to the same GameObject with in-editor notifications (#1777) - Fixed parenting warning printing for false positives (#1855)
This commit is contained in:
@@ -12,6 +12,7 @@ using Unity.Multiplayer.Tools;
|
||||
#endif
|
||||
using Unity.Profiling;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace Unity.Netcode
|
||||
@@ -45,7 +46,7 @@ namespace Unity.Netcode
|
||||
private static ProfilerMarker s_TransportDisconnect = new ProfilerMarker($"{nameof(NetworkManager)}.TransportDisconnect");
|
||||
#endif
|
||||
|
||||
private const double k_TimeSyncFrequency = 1.0d; // sync every second, TODO will be removed once timesync is done via snapshots
|
||||
private const double k_TimeSyncFrequency = 1.0d; // sync every second
|
||||
private const float k_DefaultBufferSizeSec = 0.05f; // todo talk with UX/Product, find good default value for this
|
||||
|
||||
internal static string PrefabDebugHelper(NetworkPrefab networkPrefab)
|
||||
@@ -53,7 +54,6 @@ namespace Unity.Netcode
|
||||
return $"{nameof(NetworkPrefab)} \"{networkPrefab.Prefab.gameObject.name}\"";
|
||||
}
|
||||
|
||||
internal SnapshotSystem SnapshotSystem { get; private set; }
|
||||
internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; }
|
||||
|
||||
internal MessagingSystem MessagingSystem { get; private set; }
|
||||
@@ -125,13 +125,11 @@ namespace Unity.Netcode
|
||||
public bool OnVerifyCanReceive(ulong senderId, Type messageType)
|
||||
{
|
||||
if (m_NetworkManager.PendingClients.TryGetValue(senderId, out PendingClient client) &&
|
||||
(client.ConnectionState == PendingClient.State.PendingApproval ||
|
||||
(client.ConnectionState == PendingClient.State.PendingConnection &&
|
||||
messageType != typeof(ConnectionRequestMessage))))
|
||||
(client.ConnectionState == PendingClient.State.PendingApproval || (client.ConnectionState == PendingClient.State.PendingConnection && messageType != typeof(ConnectionRequestMessage))))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning($"Message received from {nameof(senderId)}={senderId.ToString()} before it has been accepted");
|
||||
NetworkLog.LogWarning($"Message received from {nameof(senderId)}={senderId} before it has been accepted");
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -229,14 +227,12 @@ namespace Unity.Netcode
|
||||
|
||||
public NetworkSceneManager SceneManager { get; private set; }
|
||||
|
||||
public readonly ulong ServerClientId = 0;
|
||||
public const ulong ServerClientId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the networkId of the server
|
||||
/// </summary>
|
||||
private ulong m_ServerTransportId => NetworkConfig.NetworkTransport?.ServerClientId ??
|
||||
throw new NullReferenceException(
|
||||
$"The transport in the active {nameof(NetworkConfig)} is null");
|
||||
private ulong m_ServerTransportId => NetworkConfig.NetworkTransport?.ServerClientId ?? throw new NullReferenceException($"The transport in the active {nameof(NetworkConfig)} is null");
|
||||
|
||||
/// <summary>
|
||||
/// Returns ServerClientId if IsServer or LocalClientId if not
|
||||
@@ -367,16 +363,14 @@ namespace Unity.Netcode
|
||||
/// <param name="approved">Whether or not the client was approved</param>
|
||||
/// <param name="position">The position to spawn the client at. If null, the prefab position is used.</param>
|
||||
/// <param name="rotation">The rotation to spawn the client with. If null, the prefab position is used.</param>
|
||||
public delegate void ConnectionApprovedDelegate(bool createPlayerObject, uint? playerPrefabHash, bool approved,
|
||||
Vector3? position, Quaternion? rotation);
|
||||
public delegate void ConnectionApprovedDelegate(bool createPlayerObject, uint? playerPrefabHash, bool approved, Vector3? position, Quaternion? rotation);
|
||||
|
||||
/// <summary>
|
||||
/// The callback to invoke during connection approval
|
||||
/// </summary>
|
||||
public event Action<byte[], ulong, ConnectionApprovedDelegate> ConnectionApprovalCallback = null;
|
||||
|
||||
internal void InvokeConnectionApproval(byte[] payload, ulong clientId, ConnectionApprovedDelegate action) =>
|
||||
ConnectionApprovalCallback?.Invoke(payload, clientId, action);
|
||||
internal void InvokeConnectionApproval(byte[] payload, ulong clientId, ConnectionApprovedDelegate action) => ConnectionApprovalCallback?.Invoke(payload, clientId, action);
|
||||
|
||||
/// <summary>
|
||||
/// The current NetworkConfig
|
||||
@@ -565,13 +559,6 @@ namespace Unity.Netcode
|
||||
|
||||
NetworkConfig.NetworkTransport.NetworkMetrics = NetworkMetrics;
|
||||
|
||||
//This 'if' should never enter
|
||||
if (SnapshotSystem != null)
|
||||
{
|
||||
SnapshotSystem.Dispose();
|
||||
SnapshotSystem = null;
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
NetworkTimeSystem = NetworkTimeSystem.ServerTimeSystem();
|
||||
@@ -584,8 +571,6 @@ namespace Unity.Netcode
|
||||
NetworkTickSystem = new NetworkTickSystem(NetworkConfig.TickRate, 0, 0);
|
||||
NetworkTickSystem.Tick += OnNetworkManagerTick;
|
||||
|
||||
SnapshotSystem = new SnapshotSystem(this, NetworkConfig, NetworkTickSystem);
|
||||
|
||||
this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate);
|
||||
|
||||
// This is used to remove entries not needed or invalid
|
||||
@@ -800,44 +785,35 @@ namespace Unity.Netcode
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
NetworkLog.LogInfo("StartServer()");
|
||||
NetworkLog.LogInfo(nameof(StartServer));
|
||||
}
|
||||
|
||||
if (IsServer || IsClient)
|
||||
if (!CanStart(StartType.Server))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning("Cannot start server while an instance is already running");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetworkConfig.ConnectionApproval)
|
||||
{
|
||||
if (ConnectionApprovalCallback == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
"No ConnectionApproval callback defined. Connection approval will timeout");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Initialize(true);
|
||||
|
||||
var result = NetworkConfig.NetworkTransport.StartServer();
|
||||
// If we failed to start then shutdown and notify user that the transport failed to start
|
||||
if (NetworkConfig.NetworkTransport.StartServer())
|
||||
{
|
||||
IsServer = true;
|
||||
IsClient = false;
|
||||
IsListening = true;
|
||||
|
||||
IsServer = true;
|
||||
IsClient = false;
|
||||
IsListening = true;
|
||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
||||
|
||||
SpawnManager.ServerSpawnSceneObjectsOnStartSweep();
|
||||
OnServerStarted?.Invoke();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Server is shutting down due to network transport start failure of {NetworkConfig.NetworkTransport.GetType().Name}!");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
OnServerStarted?.Invoke();
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -850,26 +826,26 @@ namespace Unity.Netcode
|
||||
NetworkLog.LogInfo(nameof(StartClient));
|
||||
}
|
||||
|
||||
if (IsServer || IsClient)
|
||||
if (!CanStart(StartType.Client))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning("Cannot start client while an instance is already running");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Initialize(false);
|
||||
MessagingSystem.ClientConnected(ServerClientId);
|
||||
|
||||
var result = NetworkConfig.NetworkTransport.StartClient();
|
||||
if (!NetworkConfig.NetworkTransport.StartClient())
|
||||
{
|
||||
Debug.LogError($"Client is shutting down due to network transport start failure of {NetworkConfig.NetworkTransport.GetType().Name}!");
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
IsServer = false;
|
||||
IsClient = true;
|
||||
IsListening = true;
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -882,31 +858,21 @@ namespace Unity.Netcode
|
||||
NetworkLog.LogInfo(nameof(StartHost));
|
||||
}
|
||||
|
||||
if (IsServer || IsClient)
|
||||
if (!CanStart(StartType.Host))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning("Cannot start host while an instance is already running");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetworkConfig.ConnectionApproval)
|
||||
{
|
||||
if (ConnectionApprovalCallback == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
"No ConnectionApproval callback defined. Connection approval will timeout");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Initialize(true);
|
||||
|
||||
var result = NetworkConfig.NetworkTransport.StartServer();
|
||||
// If we failed to start then shutdown and notify user that the transport failed to start
|
||||
if (!NetworkConfig.NetworkTransport.StartServer())
|
||||
{
|
||||
Debug.LogError($"Server is shutting down due to network transport start failure of {NetworkConfig.NetworkTransport.GetType().Name}!");
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
MessagingSystem.ClientConnected(ServerClientId);
|
||||
LocalClientId = ServerClientId;
|
||||
NetworkMetrics.SetConnectionId(LocalClientId);
|
||||
@@ -942,7 +908,53 @@ namespace Unity.Netcode
|
||||
|
||||
OnServerStarted?.Invoke();
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
private enum StartType
|
||||
{
|
||||
Server,
|
||||
Host,
|
||||
Client
|
||||
}
|
||||
|
||||
private bool CanStart(StartType type)
|
||||
{
|
||||
if (IsListening)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning("Cannot start " + type + " while an instance is already running");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetworkConfig.ConnectionApproval)
|
||||
{
|
||||
if (ConnectionApprovalCallback == null)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
"No ConnectionApproval callback defined. Connection approval will timeout");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConnectionApprovalCallback != null)
|
||||
{
|
||||
if (!NetworkConfig.ConnectionApproval)
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
"A ConnectionApproval callback is defined but ConnectionApproval is disabled. In order to use ConnectionApproval it has to be explicitly enabled ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetSingleton()
|
||||
@@ -1014,6 +1026,7 @@ namespace Unity.Netcode
|
||||
internal interface INetworkManagerHelper
|
||||
{
|
||||
bool NotifyUserOfNestedNetworkManager(NetworkManager networkManager, bool ignoreNetworkManagerCache = false, bool editorTest = false);
|
||||
void CheckAndNotifyUserNetworkObjectRemoved(NetworkManager networkManager, bool editorTest = false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1133,12 +1146,6 @@ namespace Unity.Netcode
|
||||
|
||||
this.UnregisterAllNetworkUpdates();
|
||||
|
||||
if (SnapshotSystem != null)
|
||||
{
|
||||
SnapshotSystem.Dispose();
|
||||
SnapshotSystem = null;
|
||||
}
|
||||
|
||||
if (NetworkTickSystem != null)
|
||||
{
|
||||
NetworkTickSystem.Tick -= OnNetworkManagerTick;
|
||||
@@ -1274,7 +1281,11 @@ namespace Unity.Netcode
|
||||
if (!m_ShuttingDown || !m_StopProcessingMessages)
|
||||
{
|
||||
MessagingSystem.ProcessSendQueues();
|
||||
NetworkMetrics.UpdateNetworkObjectsCount(SpawnManager.SpawnedObjects.Count);
|
||||
NetworkMetrics.UpdateConnectionsCount((IsServer) ? ConnectedClients.Count : 1);
|
||||
NetworkMetrics.DispatchFrame();
|
||||
|
||||
NetworkObject.VerifyParentingStatus();
|
||||
}
|
||||
SpawnManager.CleanupStaleTriggers();
|
||||
|
||||
@@ -1288,7 +1299,6 @@ namespace Unity.Netcode
|
||||
/// This function runs once whenever the local tick is incremented and is responsible for the following (in order):
|
||||
/// - collect commands/inputs and send them to the server (TBD)
|
||||
/// - call NetworkFixedUpdate on all NetworkBehaviours in prediction/client authority mode
|
||||
/// - create a snapshot from resulting state
|
||||
/// </summary>
|
||||
private void OnNetworkManagerTick()
|
||||
{
|
||||
@@ -1419,18 +1429,15 @@ namespace Unity.Netcode
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
s_TransportDisconnect.Begin();
|
||||
#endif
|
||||
clientId = TransportIdToClientId(clientId);
|
||||
|
||||
OnClientDisconnectCallback?.Invoke(clientId);
|
||||
|
||||
m_TransportIdToClientIdMap.Remove(transportId);
|
||||
m_ClientIdToTransportIdMap.Remove(clientId);
|
||||
clientId = TransportIdCleanUp(clientId, transportId);
|
||||
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
|
||||
{
|
||||
NetworkLog.LogInfo($"Disconnect Event From {clientId}");
|
||||
}
|
||||
|
||||
OnClientDisconnectCallback?.Invoke(clientId);
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
OnClientDisconnectFromServer(clientId);
|
||||
@@ -1446,6 +1453,31 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles cleaning up the transport id/client id tables after
|
||||
/// receiving a disconnect event from transport
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ulong TransportIdCleanUp(ulong clientId, ulong transportId)
|
||||
{
|
||||
// This check is for clients that attempted to connect but failed.
|
||||
// When this happens, the client will not have an entry within the
|
||||
// m_TransportIdToClientIdMap or m_ClientIdToTransportIdMap lookup
|
||||
// tables so we exit early and just return 0 to be used for the
|
||||
// disconnect event.
|
||||
if (!IsServer && !m_TransportIdToClientIdMap.ContainsKey(clientId))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
clientId = TransportIdToClientId(clientId);
|
||||
|
||||
m_TransportIdToClientIdMap.Remove(transportId);
|
||||
m_ClientIdToTransportIdMap.Remove(clientId);
|
||||
|
||||
return clientId;
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<TMessageType, TClientIdListType>(ref TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds)
|
||||
where TMessageType : INetworkMessage
|
||||
where TClientIdListType : IReadOnlyList<ulong>
|
||||
@@ -1591,32 +1623,45 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = networkClient.OwnedObjects.Count - 1; i >= 0; i--)
|
||||
// Get the NetworkObjects owned by the disconnected client
|
||||
var clientOwnedObjects = SpawnManager.GetClientOwnedObjects(clientId);
|
||||
if (clientOwnedObjects == null)
|
||||
{
|
||||
var ownedObject = networkClient.OwnedObjects[i];
|
||||
if (ownedObject != null)
|
||||
// This could happen if a client is never assigned a player object and is disconnected
|
||||
// Only log this in verbose/developer mode
|
||||
if (LogLevel == LogLevel.Developer)
|
||||
{
|
||||
if (!ownedObject.DontDestroyWithOwner)
|
||||
NetworkLog.LogWarning($"ClientID {clientId} disconnected with (0) zero owned objects! Was a player prefab not assigned?");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle changing ownership and prefab handlers
|
||||
for (int i = clientOwnedObjects.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var ownedObject = clientOwnedObjects[i];
|
||||
if (ownedObject != null)
|
||||
{
|
||||
if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].OwnedObjects[i]
|
||||
.GlobalObjectIdHash))
|
||||
if (!ownedObject.DontDestroyWithOwner)
|
||||
{
|
||||
PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].OwnedObjects[i]);
|
||||
if (PrefabHandler.ContainsHandler(clientOwnedObjects[i].GlobalObjectIdHash))
|
||||
{
|
||||
PrefabHandler.HandleNetworkPrefabDestroy(clientOwnedObjects[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(ownedObject.gameObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(ownedObject.gameObject);
|
||||
ownedObject.RemoveOwnership();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ownedObject.RemoveOwnership();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Could(should?) be replaced with more memory per client, by storing the visibility
|
||||
|
||||
foreach (var sobj in SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
sobj.Observers.Remove(clientId);
|
||||
@@ -1764,7 +1809,7 @@ namespace Unity.Netcode
|
||||
|
||||
var message = new CreateObjectMessage
|
||||
{
|
||||
ObjectInfo = ConnectedClients[clientId].PlayerObject.GetMessageSceneObject(clientPair.Key, false)
|
||||
ObjectInfo = ConnectedClients[clientId].PlayerObject.GetMessageSceneObject(clientPair.Key)
|
||||
};
|
||||
message.ObjectInfo.Header.Hash = playerPrefabHash;
|
||||
message.ObjectInfo.Header.IsSceneObject = false;
|
||||
|
||||
Reference in New Issue
Block a user