Skip to content

A Native Collection has not been disposed, resulting in a memory leak #2862

@shrike86

Description

@shrike86

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;
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions