Unity-Technologies / com.unity.netcode.gameobjects

Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.
MIT License
2.15k stars 434 forks source link

NetworkVariable with custom struct using native array leads to a ObjectDisposedException #3064

Closed MilkyChestnut closed 1 month ago

MilkyChestnut commented 1 month ago

Description

I'm using a custom struct implementing INetworkSeriaizable for a NetworkVariable. This custom struct has a NativeArray of ints and is created with the Allocation.Persistent

I've found that I keep getting this error. Leak Detected : Persistent allocates 4 individual allocations.

When I impliment IDisposable however I get this error

ObjectDisposedException: Cannot access a disposed object.
Object name: 'The NativeArray has been disposed, it is not allowed to access it'.
        private NativeArray<int> _arrayInts;

        public CustomStruct(int size) {
            _arrayInts = new NativeArray<int>(1, Allocator.Persistent);
        }

        public void Dispose()
        {
            _arrayInts.Dispose();
        }

        public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
        {
            serializer.SerializeValue(ref _arrayInts, Allocator.Persistent);
        }

    }
    private NetworkVariable<CustomStruct> _netCustomStructs = new();

Reproduce Steps

  1. Create a custom struct implimenting INetworkSerializable
  2. Allocate a native array on the structs creation 3) Create a NetworkVariable that uses the struct 4) Play the game and receiving warnings about memory leaks

5) Add IDisposable, and impliment disposing of the array 6) Play again and when finishing the play session recieve the error about the array already being disposed.

Actual Outcome

Erros releated to a memory leak of not disposing the native array.

Errors related to the native array already being disposed when implimenting IDisposable

Expected Outcome

No errors about a memory leak or already disposing the NativeArray

Screenshots

image image

Environment

NoelStephensUnity commented 1 month ago

Hi @MilkyChestnut, Almost all things "Native" need to be allocated and disposed since you are creating memory allocations outside of managed memory. So, you are like 95% of the way to a final solution for your INetworkSeriaizable implementation.

Within your Dispose method if you make this minor adjustment you should no longer get that error message when you completely disconnect from the session and most likely things are being destroyed:

public void Dispose()
{
    if (_arrayInts.IsCreated)
    {
        _arrayInts.Dispose();
    }       
 }

The IsCreated property will let you know if the NativeArray is "created"/"allocated" or not in order to know whether you need to dispose it or not.

Let me know if this resolves your issue?

MilkyChestnut commented 1 month ago

I believe this works, thanks I appreciate it!

I do have some serious issues with NativeArrays and NativeLists that Ill discuss is another issue report.

NativeLists dont seem to want to serialize at all, and NativeArrays wont serialize any custom structs implimenting INetworkSerialize (tho will work with other serialization methods)