UnityPackageのJobについてくる2つのAPIの内の一つIJobParallelForFilter
とは何ぞや? という事を追ってみました。
- オチ
- Jobsパッケージの2つのAPI
- ScheduleAppendで要素をフィルタリングしてScheduleFilterで実行する程度の能力
- IJob「ParallelFor」Filterだから並列処理に…ならない
- 結論
- サンプルコード
オチ
時間の無駄でした。
Jobsパッケージの2つのAPI
UnityPackageでECSを導入するときによく目につくパッケージに「Jobs」というものがあります。説明文では「IJobParallelForBatch
とIjobParallelForFilter
を追加する」としか書いておらず、またマニュアルにも「このパッケージのドキュメントは無い」と堂々と記述するくらいに圧倒的なパワー力を溜めている感じのパッケージです。
IJobParallelForBatch
に関しては他のマニュアル(Custom job types)で例として挙げられていたりと、用途が無い訳では無いのですが、一方でIjobParallelForFilter
は割と探してもノーヒント。
もしかしたら役に立つかもしれないので、ちょっと追ってみました。
ScheduleAppendで要素をフィルタリングしてScheduleFilterで実行する程度の能力
IJobParallelForFilterを継承したジョブを実装すると、なんと2つのAPIが付いてきます。ScheduleAppend(...)
と ScheduleFilter(...)
です。
JobHandle ScheduleAppend( ...)
は、一言で言うなら要素をフィルタリングするAPIです。
bool Execute(int index)
の戻りがフィルターとなります。結果は NativeList<int> indices
に格納します。
一方でScheduleFilter(...)
はフィルタリングした要素だけを処理するAPIです。
ScheduleAppend(...)
の結果 true判定されている要素だけを処理してくれます。
つまり、例えば当たり判定等を考えたときに ScheduleAppend(...)
でプレイヤーの近くの敵や弾をフィルタリングし、 ScheduleFilter(...)
で実際に接触している敵や弾に対してのみ処理を行う…とかに使えそうです。
なお複数のAppendを使用する事は出来ませんでした。なので複数の条件を定義してジョブを連結して組み合わせるといった事をせず、1つの ScheduleAppend(...)
に全判定を突っ込む必要があります。
また ScheduleAppend(...)
も ScheduleFilter(...)
も、どちらも同じbool Execute(int index)
を呼びます。つまり一つのジョブでフィルタと制御を記述することは出来ません。減点1
IJob「ParallelFor」Filterだから並列処理に…ならない
上のような面倒臭さを超えても、素晴らしそうに見える理由があります。IJobParallelForFilterは「IJobParallelFor」…つまり並列処理が期待出来る点です。並列判定(書込)・並列処理(読込)は面倒くさいので、これが実現出来るなら実に素晴らしい事です。
と思って実行してみると、なんということでしょう。そこには一本のスレッド上で動作するIJobParallelForFilter
様がおられるではありませんか。
あれ? 処理が全くスレッドに分散されてないヨ?
いやいやおかしいと色々試してみても特におかしな所は無かったのでソースコードを確認してみた所、なんと JobsUtility.Schedule(...)
を使用しているではありませんか。待ち給え、そのAPIはIJob
用だ!(IJobParallelFor用はJobsUtility.ScheduleParallelFor(...)
)
つまりアレです。IJobParallelFor使ってへんのかーい!
この内容なら、NativeQueue.Concurrent
とかで並列書込してジョブで一気に処理とか、なんか他にもっと色々とやり方がありそうな気がしなくもないです。
結論
IJobParallelForFilterなんて無かった。いいね?
(強いて言うならサンプル)
サンプルコード
PlayerがEnemyに接触したらパーティクルを1つEmitする例