テラシュールブログ

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

【Unity】ECSのComponentSystem実行順をコントロールする

今回はECSのComponentSystemも実行順番をコントロールする方法についてです。

 

 

ComponentSystemの実行順番は非常に重要

ECSは無数に存在するComponentDataをComponentSystemで一括制御する事で実現しています。ソレが単なる技術デモでComponentDataとComponentSystemが一対一の関係なら大した問題にはなりません。

問題になるのは複数のComponentSystemで複数のComponentDataを制御する場合で、その場合ComponentSystemの実行順によって結果が変わってきます

例えば「Entity生成」「Entityの向きをターゲットへ変更」「Entityの向きに従って前方をチェック」「当たっているならEntityを生成」といったシステムを考えてみます。

f:id:tsubaki_t1:20180904191205j:plain

これが順番通り動くなら問題はないのですが、「Entityの向きをターゲットへ変更」の前に「Entityの向きに従って前方をチェック」が入ると、最初に向いていた方へチェックが入る事になり、思ったとおりの結果を得られなくなります。

f:id:tsubaki_t1:20180904191241j:plain

 

実行順の確認方法

まず実行順の確認方法です。
使っていて気づいたのですが、EntityDebuggerのSystem並び順は実行順で並ぶみたいです。
例えば下の場合、SampleSystem1~3を用意したのですが、実行してみると実行順はSampleSystem 2、SampleSystem 3、SampleSystm1の順でした。

f:id:tsubaki_t1:20180904175105j:plain

f:id:tsubaki_t1:20180904175211j:plain

まぁ一番確実なのはProfilerで順番を見る事ですが、処理時間が短いと探すのが大変なので、多分大丈夫だろう程度で使えそうです。

 

特定のComponentSystemの前に実行する、後に実行する

ComponentSystemはScript Execution Orderのような機能はありません。その代り、UpdateAfterUpdateBeforeというAttributeが使えます。

 このAPIComponentSystemを指定したシステムより前もしくは後に実行するように指定するというものです。PlayerLoopに登録する時、依存関係を見て実行順を作ってくれるとか云々。
下のコードの場合、System1よりSystem2が先に実行されるようになります。

gist.github.com

 なお、実はこのUpdateAfterUpdateBeforePlayerLoopのAPIにも使用できます。例えば下のように記述すると、Updateの前後に処理を挟むことも出来ます。

gist.github.comf:id:tsubaki_t1:20180904180713j:plain

なお実行のタイミングによってEntityDebuggerの表示される場所が微妙に変わる事があります。例えば下のコードでは[UpdateBefore(typeof( UnityEngine.Experimental.PlayerLoop.Initialization))]と記述した所、所属するグループがInitializationに変化しました。

f:id:tsubaki_t1:20180904180951p:plain

 

UpdateInGroupで処理のタイミングを大まかに纏める

次にUpdateAfterを特定のシステムではなく、システムをまとめた「グループ」を指定してみます。これは複数人で開発する時に重要な要素です。

例えば[A][B][C]という3つのシステムがあり、この処理後に何かをしたい場合です。この場合はUpdateAfter(c)で良いです。
では[A][B][C]に追加で[D]というシステムが増え、処理結果は[D]以降に取らなくてはいけなくなった場合、チーム全体にDというシステムが増えた事を共有する必要が出てきます。

f:id:tsubaki_t1:20180904183546j:plain

そこでグループを使用します
[A][B][C]を纏めてグループ:[G]に登録しておきます。そうすると他の人はABCの最後のシステムを把握せずともUpdateAfter(G)で良くなります。逆に「前」で実行する場合もUpdateBefore(G)で良くなります。

f:id:tsubaki_t1:20180904191658j:plain

gist.github.com上のコードを実行すると、ABCの前にX1、後にX2が実行されます。新しいシステムを追加しても、グループで囲ってる範囲に入り込むことはありません。
なお、Xをグループに紛れ込ませるとバグります。

f:id:tsubaki_t1:20180904185243j:plain

関連

Documentation for system update order · GitHub