rrbox / ecs-swift

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

Entity hierarchy #55

Closed rrbox closed 1 month ago

rrbox commented 7 months ago

以下の Component を追加します。

rrbox commented 7 months ago

Entity hierarchy と SKNode や SCNNode[^1] の hierarchy とで連携する必要があります(というより、それが一番の目的です)。SpriteKit や SceneKit[^1] での使用を前提とするなら、Graphic 関連の plugin に導入してもいいかもしれません。

[^1]: SceneKit のサポートは v0.1.0 時点では未実装です。あと、今後サポートするかも未定です...

rrbox commented 7 months ago

仕様

子 Entity 追加時に Graphic の有無をチェックする

Graphic ひもづけ時に、親の有無をチェックする

自分に親がいたら、親に Graphic があるかをチェックし、親がグラフィックを持っていたら addChild です。

Graphic ひもづけ時に、子が Graphic を持っているかチェックする

Graphic を持っていたら、自分の Graphic の子ノードとして addChild します。

子の取り合いをしない(親が複数存在する状態をつくらない & 同じ子を持たない)

Graphic と紐づいていないときもこのチェックは必要になります。

Graphic と紐づけることを必須とする場合は、SKNode が自動的に検知して実行時エラーになるので、特に注意する必要はないです。

親がデスポーンしたら子もデスポーンする

WillDespawnEvent を使えば多分できます。

注意点として、先に SKNode が削除されてしまう場合、unown let の参照先が消えることで despawn 時の自動 remove from parent 実行機能がエラーになる可能性があることです。SKNode 削除前に entity との繋がりをなくす何らかの仕組みを実装したいところです。

rrbox commented 7 months ago
let child = commands.spawn().id()

commands.spawn()
    .addChild(child)
rrbox commented 7 months ago
struct Child: Component {
    var _parent: Entity
    var parent: Entity {
        self._parent
    }
}

struct Parent: Component {
    var _children: Set<Entity>
    var children: Set<Entity> {
        self._children
    }
}
rrbox commented 4 months ago

Graphic が entity に紐づいていない場合はクラッシュする、という実装も考えられます。これは、entity hierarchy の機能が graphic の座標系に関するものだからです。

上記の実装の場合、setGraphic の際に ChildParent をコンポーネントとして追加し、entity hierarchy の管理を始めるのが最もシンプルだと思います。

また、一度 entity に紐づけられた SKNode, SCNNode を取り外せないようにするべきかもしれません。こうすることで、entity hierarchy 内の graphic が勝手に ECS 管理外になるのを観測する手間が省けます。

rrbox commented 4 months ago

Graphic は spawn 後の entity に割り当てられ、基本的に Scene resource で指定された Scene に配置されます。したがって、Add child command はすでに scene を親に持った SKNode を操作することになります。SKNode の removeFromParent を実行すればエラーなしで階層に追加できますが、「親を複数持つ entity の禁止」ができなくなります。

rrbox commented 2 months ago

Entity hierarchy と node hierarchy の連動

内部コンポーネントとして _AddChildTransaction を提案します。

内部

親 entity を nil 許容型で保持します var parentEntity: Entity?。nil の場合、コマンド実行時に SceneResource のノードが親ノードになります。

以下のような System を作成します。

  1. 第1引数 第2要素 parentEntity を使用して 第2引数から親ノードを受け取り、 addChild
  2. 第1引数 第2要素 parentEntity が nil の場合、SceneResource から SKScene を引っ張ってきて addChild
  3. 第1引数 第1要素 entity を使用して commands.entity(entity).removeComponent(_AddChildTransaction.self) を実行

Set graphic 内の addChild 処理はすべて削除し、_AddChildTransaction を追加する処理を記述します。


追記

上記のシステムの中で、コンポーネント ChildParent を追加する処理を加えましょう。