rrbox / ecs-swift

Entity Component System for swift
MIT License
3 stars 0 forks source link

Entity を Query のジェネリクスで指定して受け取る #54

Closed rrbox closed 4 months ago

rrbox commented 7 months ago

to do:

この提案を実装すると、Query が Entity を受け取るかどうかをオプションにすることができます。

v0.1.0 での Query でコンポーネントを受け取る方法はこのようになっています:

func system(query: Query<SomeComponent>) {
    query.update { entity, someComponent in

    }
}

この場合は、Entity を常に受け取るようになっており、受け取りたくない場合は _ に置き換える処置となっています。

Entity を Component に準拠させた場合は以下のように変更することができます。

func system(query: Query2<Entity, SomeComponent>) {
    query.update { entity, someComponent in

    }
}

この場合は、Entity を受け取りたくない時は query の型を Query<SomeComponent> にすることで解決できます。

func system(query: Query<SomeComponent>) {
    query.update { someComponent in

    }
}
rrbox commented 6 months ago

この提案は #15 との相性が良いです。Sparse set ではデータ(component)を配列に保管して管理し、イテレーションする際は entity を無視するのがデフォルトの挙動となります。従って、データに関連づけられた entity を受け取る方法が新たに必要となります。Entity を Component に準拠させれば、system parameter の型の構成により entity を受け取る/受け取らないを明示することができ、しかも sparse set の構造を独自に改変することなくそのまま使うことができます。

rrbox commented 5 months ago

できれば、Component として追加した entity の値を不変にしたいです。


Query のジェネリクスの型制約を Component ではなく、新たに QueryTarget を作り、Entity を Query target に準拠させます。こうすることで addComponent や removeComponent などによる上書きを防止できます。

Component を Entity 同様に Query target に準拠させれば、Query で受け取れるようになります。

ComponentRef のジェネリクスの型制約を削除します。ComponentRef のサブクラスを作成し、ImmutableRef とします。Entity は ImmutableRef に格納します。これで可変性の制御ができます。

rrbox commented 5 months ago

UnityECS のように、RO<T>, RW<T> を実装すると、Entity を完全に不変なコンポーネントとして扱えると思います。

コンポーネントを受け取りたい時は

func someSystem(query: Query2<RO<SomeComponent>, RW<SomeComponent2>>) {

}

entity も受け取りたい時は

func someSystem(query: Query3<Entity, RO<SomeComponent>, RW<SomeComponent2>>) {

}

しかし、このジェネリクスによって、Queryの更新処理を静的ディスパッチで変化させる方法がないように思います(inout 渡し/値渡しの選択を Query の型定義から判断・決定することができない)。


考察の結果、RO, RW の実装はマストではありませんでした。

rrbox commented 4 months ago

63 にて達成