いんでぃーづ

ゲームいろいろ、いろいろ自由

Unity ECS : ジョブでNativeArrayのメモリリークが起きている場合の解決方法

とりあえず動くのを優先してジョブをガリガリ書いていると、以下のようなエラー表示によく出くわします。

f:id:sugar_affordance:20201110091446p:plain

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 をクリックしてチェックを入れます。

f:id:sugar_affordance:20201110091520p:plain

すると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);

ここに詳しい説明が載ってます。

NativeContainer - Unity マニュアル

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のようなので将来的にはできるようになるかと。

NativeContainer - Unity マニュアル

C# コンパイラー - Unity マニュアル


“Unity” and Unity logos are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere, and are used under license.


免責事項

当サイトの広告バナー、リンクによって提供される情報、サービス内容について、当サイトは一切の責任を負いません。

また、当サイトの情報を元にユーザ様が不利益を被った場合にも、当サイトは一切の責任を負いません。

すべて自己責任でお願いします。