とりあえず動くのを優先してジョブをガリガリ書いていると、以下のようなエラー表示によく出くわします。
A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.
NativeArray などでメモリを動的確保してから解放しなかったのが原因でメモリリークとしてエラーが出ているようです。
ECS使う上では必ず見たことがあるエラーかと思います。
これが出た場合の解決方法です。
・環境 Unity 2020.1
スタックトレースを有効にする
Unityのメニューの Jobs > Leak Detection > Full Stack Traces をクリックしてチェックを入れます。
するとConsoleのエラー内容に、どこで確保したデータでメモリリークが発生しているかが表示されるようになります。
A Native Collection has not been disposed, resulting in a memory leak. Allocated from: Unity.Entities.BlobAssetStore:.ctor() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities.Hybrid/GameObjectConversion/BlobAssetStore.cs:26) CreateEntitySystem:Setup(Transform) (at Assets/0_MainAssets/Scripts/ECS/System/CreateEntitySystem.cs:116)
アロケーターについて
NativeArrayなどに代表されるNativeContainerは、Disposeでメモリを解放しないと、一定の条件によってメモリリークとして検出されます。 条件は アロケーター の種類によって違い、アロケーターはNativeArrayを確保するときに指定する Allocator.TempJob とかのアレです。
NativeArray<float> leakArray = new NativeArray<float>(4, Allocator.TempJob);
ここに詳しい説明が載ってます。
Allocator.Temp は関数内で Disposeしないとメモリリーク判定
Allocator.TempJob は4フレーム以内で Disposeしないとメモリリーク判定
__Allocator.Persistent は恒久確保となりメモリリークは検出されません
メモリを確保しているところをusingで囲む
リークしている場所がわかったら、その変数をDisposeするだけですが、おすすめは using ステートメント で囲ってしまうことです。
using (NativeArray<float> leakArray = new NativeArray<float>(4, Allocator.TempJob)) { // 処理 }
こうすればブロックを抜けたときに自動で変数がDisposeされます。
複数の変数を確保したときは並べてかけます。
using (NativeArray<ArchetypeChunk> chunks = AnimationBatcherQuery.CreateArchetypeChunkArray(Allocator.TempJob)) using (NativeArray<float> leakArray = new NativeArray<float>(4, Allocator.TempJob)) { // 処理 }
C#8 からはカッコ内にピリオドで並べて書けるようですが、現時点でUnityがC#7.3のようなので将来的にはできるようになるかと。