今回はECSとコンポーネントの連携についてです。
コンポーネントとECSの連携、何故?
ECSは完全にGameObject / Componentと異なるシステム上で動作していますが、一応連携する事も可能です。
ただし連携の為にECSのメリットであるメモリレイアウトの最適化やマルチスレッド対応、SIMD連携等はかなり削がれます。とは言えUnityの大半のノウハウは既にGameObject / Component上に存在し、これを無かったことにするのは勿体無いという発想だと思います。
自分は将来的(再来年のレベル)には、殆どのシステムがECS上で動作するようになると踏んでいますが(Tiny Unity等はECS前提)、まだ先の話です。
なお、今回は名前がややっこしいので、以下のルールで書いていきます。
ECS Hybrid (ECSとコンポーネントとの連携)
ECSとComponentの連携は、ECS Hybrid(ハイブリッド)の名称で呼ばれています。これは二通りの考えがあって、一つはComponentDataをComponentにする、もう一つはComponentをEntityに登録するというものです。
ComponentをEntityに登録する
まず多分使うであろう方はComponentをEntitiyに登録するというものです。
例えば現在ECSにはRigidbodyやAnimation、SpriteRendererに関する機能は実装されていません。そこで基本的な動きはGameObjectのComponentを利用するが、データの制御はECSに任せるといったハイブリットな考え方で代用します。
使い方を見てみます。
まずはGameObject側の操作ですが、GameObjectにGameObjectEntityを加えます。GameObjectEntityは同じGameObject内のコンポーネントをEntityに加えてくれるという物です。
あとはシステム側からコンポーネントへアクセスします。アクセスする方法はGroupとしてComponentArrayを要求するだけです。
例えば下のコードは、Rigidbodyを持つEntityのVelocityを書き換えてジャンプするコードです。
またGetEntitysでGroupと一致するEntityと中身を注入して、一気に処理する等も出来ます。
この使い方はECSの利点であるメモリレイアウト的にはそれ程意味は無いのですが、単純にECSからGameObjectへアクセスする上で使い勝手が良いです。たぶんピュアなECSを使う場合にもUIとの連携等で目にする機会はあるかもしれません。
ComponentDataをComponentにする
次はComponentDataをComponentにしてみます。
これの利点は単純にSceneやPrefabの仕組みをECSでも使える点です。
つまりInspectorから値を編集することが出来ます。
ComponentDataを使用しているのでメモリレイアウト的には良く高速化の恩恵が受けられるであろう反面、超絶面倒くさく、またオブジェクトの生成が速い恩恵は余り受けられなくなります。
やるべき事は単純で、ComponentDataWrapperもしくはSharedComponentDataWrapperを継承したクラスを定義するだけです。
後は作成したラッパークラスをGameObjectに追加すると、Entityとして使用できるようになります。
ComponentからComponentDataを操作する
UIやEventやその他何らかのシステムがEntityのComponentDataを操作するという事もあるかもしれません。特定のEntityに対して操作したい場合は、下のようなコードで実現出来ます。
関連
ECS概念
ピュアな方のECS
tsubakit1.hateblo.jpハイブリットECSに関して少し説明がある
github.comサバイバルシューターのECS対応版
github.com公式ECSハイブリットサンプル