Skip to content

Commit

Permalink
4.5.8
Browse files Browse the repository at this point in the history
- Fixed memory leak in ObserverConditions when using pooling.
- Fixed memory leak in ObserverConditions when destroying objects as clientHost before client-side deinitialized the object.
- Improved notes on a ReplicateState enum value.
- Improved error logging for SyncTypes.
  • Loading branch information
FirstGearGames committed Jan 21, 2025
1 parent 2e1c92a commit fdc8fcb
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Assets/FishNet/Runtime/Managing/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public static IReadOnlyList<NetworkManager> Instances
/// <summary>
/// Version of this release.
/// </summary>
public const string FISHNET_VERSION = "4.5.7";
public const string FISHNET_VERSION = "4.5.8";
/// <summary>
/// Maximum framerate allowed.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ internal NetworkObserver AddDefaultConditions(NetworkObject nob)
}
else
{
//If already setup by this manager then return.
if (result.ConditionsSetByObserverManager)
return result;

obsAdded = false;
}

Expand Down Expand Up @@ -211,6 +215,8 @@ void AddMissing(NetworkObserver networkObserver)
}
}

result.ConditionsSetByObserverManager = true;

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ internal void ReadSyncType(PooledReader reader, int writtenLength, bool asServer
if (_syncTypes.TryGetValueIL2CPP(syncTypeId, out SyncBase sb))
sb.Read(reader, asServer);
else
NetworkManager.LogWarning($"SyncType not found for index {syncTypeId} on {transform.name}, component {GetType().FullName}. Remainder of packet may become corrupt.");
NetworkManager.LogError($"SyncType not found for index {syncTypeId} on {transform.name}, component {GetType().FullName}. The remainder of the packet will become corrupt likely resulting in unforeseen issues for this tick, such as data missing or objects not spawning.");
}

if (reader.Position > endPosition)
Expand Down
24 changes: 13 additions & 11 deletions Assets/FishNet/Runtime/Object/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,16 +446,18 @@ private void OnDestroy()
if (!_initializedValusSet)
return;

/* There is however chance the object can get destroyed before deinitializing
* as clientHost. If not clientHost its safe to skip deinitializing again.
* But if clientHost, check if the client has deinitialized. If not then do
* so now for the client side. */
bool exitMethod = false;

/* If already deinitializing then FishNet is in the process of,
* or has finished cleaning up this object. */
//callStopNetwork = (ServerManager.Objects.GetFromPending(ObjectId) == null);
if (IsDeinitializing)
{
/* There is however chance the object can get destroyed before deinitializing
* as clientHost. If not clientHost its safe to skip deinitializing again.
* But if clientHost, check if the client has deinitialized. If not then do
* so now for the client side. */
bool exitMethod = false;

if (IsHostStarted)
{
if (!_onStartClientCalled)
Expand All @@ -465,18 +467,18 @@ private void OnDestroy()
{
exitMethod = true;
}

if (exitMethod)
{
NetworkBehaviour_OnDestroy();
return;
}
}

if (Owner.IsValid)
Owner.RemoveObject(this);
if (NetworkObserver != null)
NetworkObserver.Deinitialize(destroyed: true);

if (exitMethod)
{
NetworkBehaviour_OnDestroy();
return;
}

if (NetworkManager != null)
{
Expand Down
5 changes: 3 additions & 2 deletions Assets/FishNet/Runtime/Object/ReplicateState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ public enum ReplicateState : byte
/// </summary>
Invalid = 0,
/// <summary>
/// Value is seen on server, and clients when they own the object.
/// Data has been received on the object for the tick.
/// Value is seen on server and clients.
/// Client or server has data on the object for the tick.
/// Clients will only see this value on spectated objects when PredictionManager is using Appended state order.
/// </summary>
CurrentCreated = 1,
/// <summary>
Expand Down
45 changes: 30 additions & 15 deletions Assets/FishNet/Runtime/Observing/NetworkObserver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
using FishNet.Managing.Server;
using FishNet.Object;
using FishNet.Transporting;
using FishNet.Utility.Performance;
using GameKit.Dependencies.Utilities;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Serialization;

namespace FishNet.Observing
{
Expand Down Expand Up @@ -41,6 +38,13 @@ public enum ConditionOverrideType
}
#endregion

#region Internal.
/// <summary>
/// True if the ObserverManager had already added conditions for this component.
/// </summary>
internal bool ConditionsSetByObserverManager;
#endregion

#region Serialized.
/// <summary>
///
Expand Down Expand Up @@ -113,7 +117,11 @@ internal List<ObserverCondition> ObserverConditionsInternal
/// <summary>
/// True if was initialized previously.
/// </summary>
private bool _initializedPreviously;
private bool _conditionsInitializedPreviously;
/// <summary>
/// True if currently initialized.
/// </summary>
private bool _initialized;
/// <summary>
/// True if ParentNetworkObject was visible last iteration.
/// This value will also be true if there is no ParentNetworkObject.
Expand Down Expand Up @@ -143,43 +151,49 @@ internal void Deinitialize(bool destroyed)
if (_serverManager != null)
_serverManager.OnRemoteConnectionState -= ServerManager_OnRemoteConnectionState;

if (_initializedPreviously)
if (_conditionsInitializedPreviously)
{
_hasNormalConditions = false;

foreach (ObserverCondition item in _observerConditions)
{
item.Deinitialize(destroyed);
//If also destroying then destroy SO reference.
if (destroyed)
/* Use GetInstanceId to ensure the object is actually
* instantiated. If Id is negative, then it's instantiated
* and not a reference to the original object. */
if (destroyed && item.GetInstanceID() < 0)
Destroy(item);
}

//Clean up lists.
if (destroyed)
{
_observerConditions.Clear();
CollectionCaches<ObserverCondition>.Store(_timedConditions);
CollectionCaches<NetworkConnection>.Store(_nonTimedMet);
}
}

_serverManager = null;
_networkObject = null;
_initializedPreviously = false;
_initialized = false;
}

/// <summary>
/// Initializes this script for use.
/// </summary>
internal void Initialize(NetworkObject networkObject)
{
if (_initialized)
return;

_networkObject = networkObject;
_serverManager = _networkObject.ServerManager;
_serverManager.OnRemoteConnectionState += ServerManager_OnRemoteConnectionState;

if (!_initializedPreviously)
if (!_conditionsInitializedPreviously)
{
_initializedPreviously = true;
_conditionsInitializedPreviously = true;
bool ignoringManager = (OverrideType == ConditionOverrideType.IgnoreManager);

//Check to override SetHostVisibility.
Expand Down Expand Up @@ -244,10 +258,10 @@ internal void Initialize(NetworkObject networkObject)

//Timed.
_timedConditions = CollectionCaches<ObserverCondition>.RetrieveList();
foreach (ObserverCondition condition in timedConditions)
foreach (ObserverCondition timedCondition in timedConditions)
{
_observerConditions.Add(condition);
_timedConditions.Add(condition);
_observerConditions.Add(timedCondition);
_timedConditions.Add(timedCondition);
}

//Store caches.
Expand All @@ -263,6 +277,7 @@ internal void Initialize(NetworkObject networkObject)
for (int i = 0; i < _observerConditions.Count; i++)
_observerConditions[i].Initialize(_networkObject);

_initialized = true;

RegisterTimedConditions();
}
Expand Down Expand Up @@ -295,7 +310,7 @@ public ObserverCondition GetObserverCondition<T>() where T : ObserverCondition
internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool timedOnly)
{
bool currentlyAdded = (_networkObject.Observers.Contains(connection));

//True if all conditions are met.
bool allConditionsMet = true;
/* If cnnection is owner then they can see the object. */
Expand All @@ -315,7 +330,7 @@ internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool
if (parentVisible && !_lastParentVisible)
timedOnly = false;
_lastParentVisible = parentVisible;

//If parent is not visible no further checks are required.
if (!parentVisible)
{
Expand Down
17 changes: 15 additions & 2 deletions Assets/FishNet/Runtime/Observing/ObserverCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,28 @@ public abstract class ObserverCondition : ScriptableObject, IOrderable
[SerializeField]
[Range(sbyte.MinValue, sbyte.MaxValue)]
private sbyte _addOrder;
/// <summary>
/// Setting this to true can save performance on conditions which do change settings or store data at runtime.
/// This feature does not function yet but you may set values now for future implementation.
/// </summary>
public bool IsConstant => _isConstant;
[Tooltip("Setting this to true can save performance on conditions which do change settings or store data at runtime. This feature does not function yet but you may set values now for future implementation.")]
[SerializeField]
private bool _isConstant;
#endregion

#region Private.
/// <summary>
/// True if this condition is enabled.
/// </summary>
private bool _isEnabled = true;

/// <summary>
/// Gets the enabled state of this condition.
/// </summary>
/// <returns></returns>
public bool GetIsEnabled() => _isEnabled;

/// <summary>
/// Sets the enabled state of this condition.
/// If the state has changed observers will be rebuilt
Expand Down Expand Up @@ -72,6 +82,7 @@ public virtual void Initialize(NetworkObject networkObject)
{
NetworkObject = networkObject;
}

/// <summary>
/// Deinitializes this script.
/// </summary>
Expand All @@ -80,17 +91,19 @@ public virtual void Deinitialize(bool destroyed)
{
NetworkObject = null;
}

/// <summary>
/// Returns if the object which this condition resides should be visible to connection.
/// </summary>
/// <param name="connection">Connection which the condition is being checked for.</param>
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
public abstract bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed);

/// <summary>
/// Type of condition this is. Certain types are handled different, such as Timed which are checked for changes at timed intervals.
/// </summary>
/// <returns></returns>
public abstract ObserverConditionType GetConditionType();
}
}
}

0 comments on commit fdc8fcb

Please sign in to comment.