要約
- Positionプロパティを持つノード同士が親子関係になると、子の位置は親からの相対位置となる
- この親子関係の間にPositionを持たないノードを挟むと相対位置の関係を解消できる
- おまけ:循環参照を形成したい時も別のノードを間に挟むと警告を受けなくなる
環境:Godot4.2+ C#(.Net Framework6.0)
親子関係の相対座標の解消
シューティングゲームを作っていると個々のゲームオブジェクトの位置情報を更新して自機や弾の座標を更新していきますが、親子関係にあるシーンやノード(=ゲームオブジェクト)の子のPositionプロパティは、親のPositionからの相対位置として扱われます。
ほとんどの場合これはよろしくない振る舞いです。例えば自機(親)から発射した弾(子)が親の移動に伴って上下左右に引きずられるのは、意図した振る舞いではないでしょう。
これを回避するためにゲーム座標系の基準となるノードを配置し、全てのゲームオブジェクトがその子となるようGetParent().GetParent().GetParent()....AddChild()のような方式もありますが、途中にPositionプロパティを持たないゲームオブジェクトを挟むことでも回避出来ます。
この構造は自機のコード量を減らして見通しを良くすることにも貢献するので、個人的にも気に入ってます。
シーン構造
上図では自機(Ship)がArea2D、弾ジェネレーターがNode、弾(Bullet)がArea2Dの派生になります。赤矢印が親子関係を表しています。弾ジェネレーターはPositionを持たないため、ジェネレータの子となった弾のPositionは自機のPositionの影響をうけません。
何度も GetParent()と書かずに済むのでコード上もシンプルな記述を維持できます。
手前味噌になりますがこの方式を用いた制作例のご紹介。
おまけ(循環参照の解消)
スイカゲームのクローンをイメージしてください。雑な動画ですがだいたいこんなゲームです。
このゲームでは衝突したボール同士から新たなボールを生成する事になります。このような構造のゲームではボールシーンが自分自身を参照できるとよいのですが、Godotエディタはこれを循環参照として警告を発します。
自己参照を行いたいシーンの参照先に別のシーンを一度中継することで、警告を解消できます。
これは警告の解消を目的とした局所的な構造変更の話であり親子関係によるPositionの相対座標関係の解消と直接の関係はありませんが、BallGeneratorがPositionを持たないことから先の問題にたいしても同時に解決できる構造となっています。