※某クラウドサービスのA〇SのECSとは関係ないです。
UnityではECSが1.0になりました。
Rust製ゲームエンジンのbevyではECSが根幹に据えられています。
このECSについて解説してみたいと思います。
コンポーネント指向
まずECSの前のコンポーネント指向について触れたいと思います。
コンポーネント指向とは機能をコンポーネントにまとめ、そのコンポーネントをまとめたオブジェクトを作り上げることによって作り上げる設計です。
アクションゲームで例えるなら、キャラクターというオブジェクトは、
- ここに描画するという情報をまとめた座標(transform)のコンポーネント
- どのように描画するかのアニメーションのコンポーネント
- 物理演算用のコンポーネント
- 入力に対して動作させるためのコンポーネント
- ロジックの状態管理のコンポーネント
などに分かれることになります。
これらのコンポーネントが一つの物体に付与されまず。それぞれが毎フレームの処理をし、また他のコンポーネントにmessageを送ったりすることでゲームの動きとなっていきます。
例えば物理演算で座標を変更したり、ロジックによってアニメーションを変化させたりなどです。
このコンポーネント指向ですが機能同士の分離はしてもデータの分離はされていないです。
そのため機能の再利用するときに(悪しき)継承などを使ったりすることが多いです。
UnityではほとんどのコンポーネントMonoBehaviour
が基底に置かれていたりします。
ECS
ここで機能とデータも分離してしまおうとするのがデータ指向になります。
その中の一つがECSになります。
Entity Component Systemはその名の通り、
- Entity 物体
- Component 要素、属性
- System 機能、法則
に分割していく設計です。
従来のComponent指向の場合はComponentとSystemが一体と化していました。
そのためこの属性はどの機能と結びつくかに依存したものになっていました。
なので複数の機能で同じデータを使いたい場合メッセージを送りあったり別のComponentを握り続ける必要があります。
ECSにおいてはComponentはただのデータの塊です。Systemが複数のComponentを利用して処理を行いComponentを変更したりします。
概念的な例
ECSは次のように考えると理解しやすいと思います。
Entity
まずEntityは物体です。
人だったり車だったりします。
人はプレーヤーだったりNPCだったり、キャラごとの違いがあったりしますが、ひとまず物は単なるEntityとして捨象して考えます。
Component
次にComponentは属性です。
現実にあるものなら、人でも車でも座標情報(x,y,zや向いている方向)があります。
移動しているなら速度を持ちます。
プレーヤーとしての属性をもったりNPCの属性を持たせたりして物体を具象化していきます。
しかしだけではComponentはただの属性、情報です。
Componentがあるだけではなんの変化が起きません。
System
ここでSystemが入ってきます。Systemとは法則です。
物理法則というSystemを定義することで「速度があれば座標が変わる」、「力が加われば加速度が働く」、「重さがあれば重力が加わる」などの動きが定義されます。
アクションゲームなら「入力でキャラクターの速度を変更する」「体力が0になれば死んだ状態にする」などの法則を設定していきます。
World
そうやって一つの「世界」を定義していくのがECSになります。
ちなみにECSではこれらをWorld
という単位に格納していきます。
ゲームの中で一つの世界を作り上げると考えるとロマンを感じる名前ですね。
ECSの利点
ECSの利点としてはデータと機能が完全に分離しているのでパフォーマンス的に優れているところがあります。
SystemではあるComponent群があるEntityをQueryで取得してそれらに変更を加えていくというような形をとります。大抵のECSは要求するComponentが何かを引数で書いて登録すればライブラリ側がQueryなどをしてくれますが、並列化できるところは自動でしてくれます。またQueryを手書きすることでさらに効率よくすることができます。(なのでECSはただのバッチ処理とみることもできます。)
またデータが分離しているので機能間の通信とかを考えないで良くなります。
単純にSystemのレイヤーでどの機能が動くかだけ考えればいいです。
逆にECSの欠点としてSystemのスケジュールが複雑になることがあるかもしれません。
まとめ
ざっくりとした概念は以上になります。
エンジンによって細かい差異はあると思いますが、考え方としては同じようになっているはずです。