末端のクソブログ

末端のクソブログ

クソブログ の 末端 にある クソブログ へ ようこそ

2023.8.28(ECSを実装しようと思う話)

先日導入したfbx sdkですがまだ読み込み部分は実装していません。よく考えれば3dモデルには階層構造があるのです。エグゾディアみたいにパーツが分解されていたりして、もしこのまま読み込めば「右足だけ揃わない!」なんてことになりかねません。

 

というのも今実装している分では描画機能しか存在していません。RenderComponentというクラスに、描画に必要な情報を持たせています。階層構造とかオブジェクトとか一切実装していません。

 

つまりこのRenderComponentを持たせる階層構造付きのオブジェクトを実装しなければ全てのメッシュノードを描画したとしても動かしたらバラバラに砕け散ります。

 

ところで階層構造付きのゲームオブジェクトの実装方法ですが、よくあるのは以下の二つだと思います。

 

コンポーネント指向

Unityとかで見るやつです。

オブジェクト指向で作るぞ!と思うと継承を使いまくった実装になると思います。

つまりゲームオブジェクトの親クラスGameObjectを実装して、操作可能オブジェクトならこれを継承したControllableGameObject、更にプレイヤー機能をつけようとするとこれをさらに継承して……。しかも操作可能かつレンダリング可能とかだとそれぞれの機能を持った親クラスを多重継承しなきゃいけません。

継承より包合、ということでそれぞれの機能をコンポーネントクラスとしてGameObjectに持たせるのがコンポーネント指向、ということです。

メリットは書きやすいことだと思います。オブジェクトごとに更新するってのは分かりやすーいって僕は思います。実装したことはありますが結構単純なつくりをしているので実装難易度も低いです.

 

ECS

えんてぃてぃ、こんぽーねんと、しすてむっていうのです。結局コンポーネントやんけ!ってなりますがデータの持ち方が違います。

コンポーネント指向ではオブジェクトごとにコンポーネントを持っているのでどう丁寧に作ってもオブジェクトごとに連続したメモリがあって、そこにコンポーネントのデータが並ぶということになります。そのオブジェクトもバラバラにあるのでキャッシュ効率が悪いです。これが結構致命的で、基本的にプログラムではメモリアクセスがボトルネックになるのでキャッシュを使えないのはヤバヤバです。

という反省を踏まえてecsではコンポーネントごとの配列を持ってentityと呼ばれる配列のindexを保持します。つまりあるentityを持つオブジェクトのコンポーネントはそれぞれの配列のindexがentityである場所にあると言うことです。

コンポーネントの更新はsystemと呼ばれる、つまりコンポーネントの配列を受け取る関数で行います。更新時に連続したコンポーネントのメモリを読み込むため、キャッシュに乗りやすいということです。

C++でECSを作ってみた - Qiita

ここを読んだら具体的な実装がある程度わかると思います。

 

ECSがナウいのでECSを実装します。

ただ上記の記事にはentityの階層構造とかがなさげだったので既存のライブラリを見て勉強しようと思います。

GitHub - skypjack/entt: Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

fbx sdkは既に僕のキャッシュから追い出されたので当分はECSについて調べようかと思います。