-
Notifications
You must be signed in to change notification settings - Fork 464
Description
Description
I am using NetworkList's but I keep getting exceptions in the editor related to a memory leaks. I don't really have reproduction steps, but it seems to happen frequently. Often, I will make code changes during run time and then stop and restart my server and client to test and on startup the exceptions will occur.
I am initialising the NetworkList in awake and I always call base.OnDestroy in my overriden OnDestroy methods.
Environment
- OS: [Windows 11]
- Unity Version: [2023.2.13f1]
- Netcode Version: [1.8.1]
Additional Context
Exception Message:
A Native Collection has not been disposed, resulting in a memory leak. Allocated from:
Unity.Collections.NativeList1:.ctor(Int32, AllocatorHandle) (at .\Library\PackageCache\[email protected]\Unity.Collections\NativeList.cs:116) Unity.Netcode.NetworkList1:.ctor() (at .\Library\PackageCache\[email protected]\Runtime\NetworkVariable\Collections\NetworkList.cs:15)
System.Reflection.RuntimeConstructorInfo:InternalInvoke(RuntimeConstructorInfo, Object, Object[], Exception&)
System.Reflection.RuntimeConstructorInfo:InternalInvoke(Object, Object[], Boolean)
System.RuntimeType:CreateInstanceMono(Boolean, Boolean)
System.RuntimeType:CreateInstanceSlow(Boolean, Boolean, Boolean, Boolean)
System.RuntimeType:CreateInstanceDefaultCtor(Boolean, Boolean, Boolean, Boolean, StackCrawlMark&)
System.Activator:CreateInstance(Type, Boolean, Boolean)
System.Activator:CreateInstance(Type, Boolean)
Unity.Netcode.Editor.NetworkBehaviourEditor:RenderNetworkVariable(Int32) (at .\Library\PackageCache\[email protected]\Editor\NetworkBehaviourEditor.cs:72)
Unity.Netcode.Editor.NetworkBehaviourEditor:OnInspectorGUI() (at .\Library\PackageCache\[email protected]\Editor\NetworkBehaviourEditor.cs:268)
UnityEditor.UIElements.<>c__DisplayClass74_0:b__0()
UnityEngine.UIElements.IMGUIContainer:DoOnGUI(Event, Matrix4x4, Rect, Boolean, Rect, Action, Boolean)
UnityEngine.UIElements.IMGUIContainer:DoMeasure(Single, MeasureMode, Single, MeasureMode)
UnityEngine.UIElements.VisualElement:Measure(VisualElement, LayoutNode&, Single, LayoutMeasureMode, Single, LayoutMeasureMode, LayoutSize&)
UnityEngine.UIElements.Layout.LayoutDelegates:InvokeMeasureFunction(LayoutNode&, Single, LayoutMeasureMode, Single, LayoutMeasureMode, LayoutSize&)
UnityEngine.UIElements.Layout.LayoutNative:CalculateLayout(IntPtr, Single, Single, Int32, IntPtr)
UnityEngine.UIElements.Layout.LayoutProcessorNative:UnityEngine.UIElements.Layout.ILayoutProcessor.CalculateLayout(LayoutNode, Single, Single, LayoutDirection)
UnityEngine.UIElements.Layout.LayoutProcessor:CalculateLayout(LayoutNode, Single, Single, LayoutDirection)
UnityEngine.UIElements.Layout.LayoutNode:CalculateLayout(Single, Single)
UnityEngine.UIElements.UIRLayoutUpdater:Update()
UnityEngine.UIElements.VisualTreeUpdater:UpdateVisualTreePhase(VisualTreeUpdatePhase)
UnityEngine.UIElements.Panel:UpdateWithoutRepaint()
UnityEditor.EditorElementUpdater:CreateInspectorElementsForMilliseconds(Int64)
UnityEditor.PropertyEditor:Update()
UnityEditor.HostView:SendUpdate()
UnityEditor.EditorApplication:Internal_CallUpdateFunctions()
Example usage of NetworkList:
public class NetworkActionState : NetworkBehaviour
{
public NetworkList<CharacterAction> CharacterActions { get => _characterActions; }
[Inject] IPublisher<CharacterActionsInitialisedMessage> _charActionsInitPub;
IServerCharacter _serverCharacter;
NetworkList<CharacterAction> _characterActions;
private void Awake()
{
_characterActions = new();
_serverCharacter = GetComponent<IServerCharacter>();
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override void OnNetworkSpawn()
{
if (!IsServer) { enabled = false; }
else
{
if (_serverCharacter is ServerEnemy serverEnemy)
{
}
else if (_serverCharacter is ServerPlayer serverPlayer)
{
StartCoroutine(WaitToInit(serverPlayer));
}
}
}
IEnumerator WaitToInit(ServerPlayer serverPlayer)
{
PersistentPlayer persistentPlayer = null;
yield return new WaitUntil(() => GameDataSource.Instance.PersistentPlayerRuntimeCollection.TryGetPlayer(OwnerClientId, out persistentPlayer));
Initialise(persistentPlayer);
}
void Initialise(PersistentPlayer persistentPlayer)
{
var networkCharActions = persistentPlayer.NetworkCharacterState.InGameChar.Value.Actions;
var actionData = JsonConvert.DeserializeObject<CharacterActions>(networkCharActions);
foreach (var action in actionData.Actions)
{
var actionId = new ActionID { ID = action.ActionID };
CharacterAction charAction = new()
{
ActionID = actionId,
Learnt = action.Learnt,
};
var serializedAction = JsonConvert.SerializeObject(charAction);
Utils.Logger.LogInformation($"Adding new character action: {serializedAction}", LoggingCategory.Actions);
_characterActions.Add(charAction);
}
StartCoroutine(WaitToPublishCharacterActionsInitMessage());
}
IEnumerator WaitToPublishCharacterActionsInitMessage()
{
yield return new WaitForEndOfFrame();
_charActionsInitPub.Publish(new CharacterActionsInitialisedMessage());
}
public bool TryFindAction(ActionID actionId, out CharacterAction characterAction)
{
characterAction = new CharacterAction();
for (int i = 0; i < _characterActions.Count; i++)
{
if (_characterActions[i].ActionID == actionId)
{
characterAction = _characterActions[i];
break;
}
}
return characterAction.ActionID.ID != 0;
}
}