ECSでNullReferenceExceptionが発生する
UNITY ECSベースでゲームを作っているとき、以下のような、既に消えたEntityやGameObjectにアクセスしてます、的なエラーに悩まされることがあります。
NullReferenceException: Object reference not set to an instance of an object
Unity.Entities.CompanionGameObjectUpdateTransformSystem.OnUpdate () (at ./Library/PackageCache/com.unity.entities@1.0.16/Unity.Transforms.Hybrid/CompanionGameObjectUpdateTransformSystem.cs:114)
単純にスクリプトの設計ミスで、修正できれば良いですが、例えば以下のような点を考慮済みでもエラーが発生すると、とても悩みます。
・削除するEntityには、まず「DestroyEntityTag」的なコンポーネントをつけて、纏めて処理している
・[UpdateInGroup(typeof(LateSimulationSystemGroup))]
や[UpdateAfter(typeof(EndSimulationEntityCommandBufferSystem))]の付与により、Entityの削除は、フレームの中でも、最後に実行している
・if (entityManager.HasComponent(entity)) 等で、先にEntityが存在するか確認してスクリプトを処理している
そんなとき、解決に役立った方法を備忘録として残します。
var entity = GetEntity(TransformUsageFlags.None); にする。
Authoring時に、深く考えずにvar entity = GetEntity(TransformUsageFlags.Dynamic);に設定することがありますが、DynamicにするとGameObjectとEntityが常に情報のやり取りをしあうので、ここでEntityが削除されているのにアクセスしてしまう、的なエラーが出ることがあります。
出ないこともあるので、再現性が低くて悩ましいところですが、エラーが出る可能性がある箇所は潰しておくべきですし、無駄な処理を省けるので、重要な設定です。