Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.netcode.gameobjects/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Additional documentation and release notes are available at [Multiplayer Documen

### Changed

- Improved performance around the NetworkBehaviour component. (#3687)

### Deprecated

Expand Down
127 changes: 66 additions & 61 deletions com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ internal enum __RpcExecStage
internal FastBufferWriter __beginSendServerRpc(uint rpcMethodId, ServerRpcParams serverRpcParams, RpcDelivery rpcDelivery)
#pragma warning restore IDE1006 // restore naming rule violation check
{
if (m_NetworkObject == null && !IsSpawned)
{
throw new RpcException("The NetworkBehaviour must be spawned before calling this method.");
}

return new FastBufferWriter(k_RpcMessageDefaultSize, Allocator.Temp, k_RpcMessageMaximumSize);
}

Expand Down Expand Up @@ -142,7 +147,7 @@ internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
{
NetworkManager.NetworkMetrics.TrackRpcSent(
NetworkManager.ServerClientId,
NetworkObject,
m_NetworkObject,
rpcMethodName,
__getTypeName(),
rpcWriteSize);
Expand All @@ -155,6 +160,11 @@ internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
internal FastBufferWriter __beginSendClientRpc(uint rpcMethodId, ClientRpcParams clientRpcParams, RpcDelivery rpcDelivery)
#pragma warning restore IDE1006 // restore naming rule violation check
{
if (m_NetworkObject == null && !IsSpawned)
{
throw new RpcException("The NetworkBehaviour must be spawned before calling this method.");
}

return new FastBufferWriter(k_RpcMessageDefaultSize, Allocator.Temp, k_RpcMessageMaximumSize);
}

Expand Down Expand Up @@ -206,7 +216,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
continue;
}
// Check to make sure we are sending to only observers, if not log an error.
if (networkManager.LogLevel >= LogLevel.Error && !NetworkObject.Observers.Contains(targetClientId))
if (networkManager.LogLevel >= LogLevel.Error && !m_NetworkObject.Observers.Contains(targetClientId))
{
NetworkLog.LogError(GenerateObserverErrorMessage(clientRpcParams, targetClientId));
}
Expand All @@ -223,7 +233,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
continue;
}
// Check to make sure we are sending to only observers, if not log an error.
if (networkManager.LogLevel >= LogLevel.Error && !NetworkObject.Observers.Contains(targetClientId))
if (networkManager.LogLevel >= LogLevel.Error && !m_NetworkObject.Observers.Contains(targetClientId))
{
NetworkLog.LogError(GenerateObserverErrorMessage(clientRpcParams, targetClientId));
}
Expand All @@ -232,7 +242,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
}
else
{
var observerEnumerator = NetworkObject.Observers.GetEnumerator();
var observerEnumerator = m_NetworkObject.Observers.GetEnumerator();
while (observerEnumerator.MoveNext())
{
// Skip over the host
Expand Down Expand Up @@ -274,7 +284,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
{
networkManager.NetworkMetrics.TrackRpcSent(
targetClientId,
NetworkObject,
m_NetworkObject,
rpcMethodName,
__getTypeName(),
rpcWriteSize);
Expand All @@ -286,20 +296,20 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
{
networkManager.NetworkMetrics.TrackRpcSent(
targetClientId,
NetworkObject,
m_NetworkObject,
rpcMethodName,
__getTypeName(),
rpcWriteSize);
}
}
else
{
var observerEnumerator = NetworkObject.Observers.GetEnumerator();
var observerEnumerator = m_NetworkObject.Observers.GetEnumerator();
while (observerEnumerator.MoveNext())
{
networkManager.NetworkMetrics.TrackRpcSent(
observerEnumerator.Current,
NetworkObject,
m_NetworkObject,
rpcMethodName,
__getTypeName(),
rpcWriteSize);
Expand All @@ -315,6 +325,10 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
internal FastBufferWriter __beginSendRpc(uint rpcMethodId, RpcParams rpcParams, RpcAttribute.RpcAttributeParams attributeParams, SendTo defaultTarget, RpcDelivery rpcDelivery)
#pragma warning restore IDE1006 // restore naming rule violation check
{
if (m_NetworkObject == null && !IsSpawned)
{
throw new RpcException("The NetworkBehaviour must be spawned before calling this method.");
}
if (attributeParams.RequireOwnership && !IsOwner)
{
throw new RpcException("This RPC can only be sent by its owner.");
Expand Down Expand Up @@ -546,6 +560,11 @@ internal bool IsBehaviourEditable()
((networkManager.DistributedAuthorityMode && m_NetworkObject.IsOwner) || (!networkManager.DistributedAuthorityMode && networkManager.IsServer));
}

internal void SetNetworkObject(NetworkObject networkObject)
{
m_NetworkObject = networkObject;
}

// TODO: this needs an overhaul. It's expensive, it's ja little naive in how it looks for networkObject in
// its parent and worst, it creates a puzzle if you are a NetworkBehaviour wanting to see if you're live or not
// (e.g. editor code). All you want to do is find out if NetworkManager is null, but to do that you
Expand Down Expand Up @@ -635,43 +654,32 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId)
/// </summary>
internal void UpdateNetworkProperties()
{
var networkObject = NetworkObject;
// Set NetworkObject dependent properties
if (networkObject != null)
{
var networkManager = NetworkManager;
// Set identification related properties
NetworkObjectId = networkObject.NetworkObjectId;
IsLocalPlayer = networkObject.IsLocalPlayer;

// This is "OK" because GetNetworkBehaviourOrderIndex uses the order of
// NetworkObject.ChildNetworkBehaviours which is set once when first
// accessed.
NetworkBehaviourId = networkObject.GetNetworkBehaviourOrderIndex(this);

// Set ownership related properties
IsOwnedByServer = networkObject.IsOwnedByServer;
IsOwner = networkObject.IsOwner;
OwnerClientId = networkObject.OwnerClientId;

// Set NetworkManager dependent properties
if (networkManager != null)
{
IsHost = networkManager.IsListening && networkManager.IsHost;
IsClient = networkManager.IsListening && networkManager.IsClient;
IsServer = networkManager.IsListening && networkManager.IsServer;
LocalClient = networkManager.LocalClient;
HasAuthority = networkObject.HasAuthority;
ServerIsHost = networkManager.IsListening && networkManager.ServerIsHost;
}
}
else // Shouldn't happen, but if so then set the properties to their default value;
var networkObject = m_NetworkObject;
var networkManager = NetworkManager;

// Set identification related properties
NetworkObjectId = networkObject.NetworkObjectId;
IsLocalPlayer = networkObject.IsLocalPlayer;

// This is "OK" because GetNetworkBehaviourOrderIndex uses the order of
// NetworkObject.ChildNetworkBehaviours which is set once when first
// accessed.
NetworkBehaviourId = networkObject.GetNetworkBehaviourOrderIndex(this);

// Set ownership related properties
IsOwnedByServer = networkObject.IsOwnedByServer;
IsOwner = networkObject.IsOwner;
OwnerClientId = networkObject.OwnerClientId;

// Set NetworkManager dependent properties
if (networkManager != null)
{
OwnerClientId = NetworkObjectId = default;
IsOwnedByServer = IsOwner = IsHost = IsClient = IsServer = ServerIsHost = default;
NetworkBehaviourId = default;
LocalClient = default;
HasAuthority = default;
IsHost = networkManager.IsListening && networkManager.IsHost;
IsClient = networkManager.IsListening && networkManager.IsClient;
IsServer = networkManager.IsListening && networkManager.IsServer;
LocalClient = networkManager.LocalClient;
HasAuthority = networkObject.HasAuthority;
ServerIsHost = networkManager.IsListening && networkManager.ServerIsHost;
}
}

Expand Down Expand Up @@ -752,8 +760,11 @@ public virtual void OnNetworkDespawn() { }
/// </summary>
public virtual void OnNetworkPreDespawn() { }

internal void NetworkPreSpawn(ref NetworkManager networkManager)
internal void NetworkPreSpawn(ref NetworkManager networkManager, NetworkObject networkObject)
{
m_NetworkObject = networkObject;
UpdateNetworkProperties();

try
{
OnNetworkPreSpawn(ref networkManager);
Expand All @@ -767,12 +778,10 @@ internal void NetworkPreSpawn(ref NetworkManager networkManager)
internal void InternalOnNetworkSpawn()
{
IsSpawned = true;
// Initialize the NetworkVariables so they are accessible in OnNetworkSpawn;
InitializeVariables();
UpdateNetworkProperties();
}

internal void VisibleOnNetworkSpawn()
{
try
{
OnNetworkSpawn();
Expand All @@ -782,9 +791,10 @@ internal void VisibleOnNetworkSpawn()
Debug.LogException(e);
}

// Initialize again in case the user's OnNetworkSpawn changed something
InitializeVariables();

if (NetworkObject.HasAuthority)
if (m_NetworkObject.HasAuthority)
{
// Since we just spawned the object and since user code might have modified their NetworkVariable, esp.
// NetworkList, we need to mark the object as free of updates.
Expand Down Expand Up @@ -872,11 +882,10 @@ public virtual void OnGainedOwnership() { }

internal void InternalOnGainedOwnership()
{
UpdateNetworkProperties();
// New owners need to assure any NetworkVariables they have write permissions
// to are updated so the previous and original values are aligned with the
// current value (primarily for collections).
if (OwnerClientId == NetworkManager.LocalClientId)
if (IsOwner)
{
UpdateNetworkVariableOnOwnershipChanged();
}
Expand Down Expand Up @@ -907,12 +916,6 @@ internal void InternalOnOwnershipChanged(ulong previous, ulong current)
/// </summary>
public virtual void OnLostOwnership() { }

internal void InternalOnLostOwnership()
{
UpdateNetworkProperties();
OnLostOwnership();
}

/// <summary>
/// Gets called when the parent NetworkObject of this NetworkBehaviour's NetworkObject has changed.
/// </summary>
Expand Down Expand Up @@ -1104,7 +1107,7 @@ internal void NetworkVariableUpdate(ulong targetClientId, bool forceSend = false

// Getting these ahead of time actually improves performance
var networkManager = NetworkManager;
var networkObject = NetworkObject;
var networkObject = m_NetworkObject;
var behaviourIndex = networkObject.GetNetworkBehaviourOrderIndex(this);
var messageManager = networkManager.MessageManager;
var connectionManager = networkManager.ConnectionManager;
Expand Down Expand Up @@ -1190,7 +1193,7 @@ private bool CouldHaveDirtyNetworkVariables()
}
// If it's dirty but can't be sent yet, we have to keep monitoring it until one of the
// conditions blocking its send changes.
NetworkManager.BehaviourUpdater.AddForUpdate(NetworkObject);
NetworkManager.BehaviourUpdater.AddForUpdate(m_NetworkObject);
}
}

Expand Down Expand Up @@ -1551,12 +1554,12 @@ internal virtual void InternalOnDestroy()
public virtual void OnDestroy()
{
InternalOnDestroy();
if (NetworkObject != null && NetworkObject.IsSpawned && IsSpawned)
if (m_NetworkObject != null && m_NetworkObject.IsSpawned && IsSpawned)
{
// If the associated NetworkObject is still spawned then this
// NetworkBehaviour will be removed from the NetworkObject's
// ChildNetworkBehaviours list.
NetworkObject.OnNetworkBehaviourDestroyed(this);
m_NetworkObject.OnNetworkBehaviourDestroyed(this);
}

// this seems odd to do here, but in fact especially in tests we can find ourselves
Expand All @@ -1575,6 +1578,8 @@ public virtual void OnDestroy()
{
NetworkVariableFields[i].Dispose();
}

m_NetworkObject = null;
}
}
}
Loading