テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】ECSで複数のComponentGroupを使う場合

複数のComponentGroupを使う

ComponentGroupは、Systemが処理するEntity(及びComponent)を取得する為に使用します。データ処理の起点とも言って良いです。

このComponentGroupですが、一つのSystem内に複数持つことが出来ます。例えばキャラクターとアイテムといった 異なる特性のEntity同士をかけ合わせて計算したい場合 など、色々な要因で複数のComponentGroupを使いたくなります。

全く異なるComponentGroupを複数定義する場合はRequireForUpdateを使う

Systemは有り難い事に、ComponentGroupが要求するEntityが一つも無い場合は、動作しないようになっています。完全にシステムを停止する訳ではないのでコストが完全に消滅する訳ではないですが、ほぼ負荷は無くなります。 これは外部からオブジェクトの状態を観測してSystemをON/OFFするよりは理に適っているかなと個人的には思います。

f:id:tsubaki_t1:20190310214225j:plain

問題は、ComponentGroupを複数要求していた場合 どれか一つでも条件を達成してしまっていれば動いてしまう という点です。

例えば「プレイヤーの位置(Group1)」を「敵(Group2)」が追跡するようなプログラムの場合、「プレイヤー(Group1)」が消滅してもプレイヤーを追跡するプログラムは停止しません。

f:id:tsubaki_t1:20190310214122j:plain

こういった場合には、RequireForUpdate( ComponentGroup )RequireSingletonForUpdate<T>()を使用します。このAPIOnCreateManager()等で呼んでおけば、該当のComponentGroupが全て揃わなければSystemは動作しません

  • 単純に複数のComponentGroupを定義した場合:OR
  • RequireForUpdateを使用した場合:AND

と思っておけば良さそうです。まぁANDとORを組み合わせた複雑な条件分岐は出来ないんですが。

f:id:tsubaki_t1:20190310215932j:plain

gist.github.com

設定違いという点で複数のComponentGroupを使用したい場合は、ChunkIterationを考える

用途は同じだがパラメーターが違う的な意味で複数のComponentGroupが必要という場合もあります。

例えばColliderの形状で、BoxもあればSphereもあります。この2つの役割は本質的には同じですが、保有するパラメーターは全く別物になるため、異なるComponentDataが適応されます。

こういったケースでは以前は複数のComponentGroupを定義していましたが、 現状だとChunkIterationを使用することが推奨される と思います。

tsubakit1.hateblo.jp

もちろん、ComponentData内に複数のケースでのCollider設定を突っ込むことは可能でしょうが、メモリレイアウト的に無駄が多いのと、同じ処理を繰り返せないという点からECS向きではありません。

感想

IJobProcessComponentDataなど、ジョブの発行それ自体に地味なコストがある場合は、RequireForUpdateで不要なればSystemが動作しないように停止しておきたい所です。まぁOnUpdateの最初でComponentGroupの長さを測って即returnすれば同じようなものでしょうが。

ところでChunkIterationがある今、複数のComponentGroupでORになるって、使うケースあるんですかね