無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、 Polygon2D ノードのポリゴン情報を CollisionPolygon2D ノードにコピーして、見た目と当たり判定領域を一致させた前回のスクリプトでは、ノードの移動・回転・拡大に対応していなかったので、対応前の問題の確認と改善したスクリプトによる結果を紹介します。
#以前参考にさせていただいたスクリプトは、そこまで対応する必要のない状況で使われていました。
※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※紹介するスクリプトは自己責任でお使いください。
前回の記事
前回は、Polygon2D ノードを使ってデザインした地形の上を、 CharacterBody2D ノードを使ったキャラクターが移動する実装の手順を紹介しました。
新しい地形を複製から作成
前回は、Polygon2D のポリゴン表示に合わせた CollisionPolygon2D による当たり判定によって、キャラクターが乗ることができる地形を作りました。
今回は、その地形のノード群を複製後、編集して、新しい地形を作成します。
シーンドックで、複製したいノード(複数ある場合はその最上位のノード)を右クリックして表示されるメニュー「複製」を選択します。
複製した Terrain ノードの下位にあるポリゴンの見た目を設定する Polygon2D を編集します。
※当たり判定領域の CollisionPolygon2D は前回のスクリプトにより開始時に自動的にポリゴン情報をコピーして設定されます。
不要な頂点は Delete キーで削除でき、頂点をマウスドラッグして移動できます。
複製することにより、簡単に地形を追加できました。
Polygon2D ノードを移動すると当たり判定が一致しない
しかし、Polygon2D ノードのポリゴンの編集の際に、ポリゴンの頂点の移動ではなく、ノード全体を思わず移動したせいで、キャラクターが地形をすり抜けてしまう問題が発生しました。
この原因は Polygon2D ノードの見た目のポリゴンと、 CollisionPolygon2D ノードの当たり判定のポリゴンの形は同じだけど、位置が異なることでした。
ポリゴンの頂点の移動では、ノード自体の位置は変わりませんが、思わず移動してしまうとノードの位置がずれてしまいます。
ノードの移動はよく行われるものなので、これに対応するために、ポリゴン情報をコピーするスクリプトに Polygon2D ノードの位置を CollisionPolygon2D にコピーする処理を追加します。
※スクリプト全体はあとで紹介します。
node_collision_pollygon2d.position = node_polygon2d.position
これにより、見た目の Polygon2D と、当たり判定領域の CollisionPolygon2D の位置が同じになり、地形をすりぬけないようになりました。
回転・拡大にも対応
ツールバーには移動モードの他に、回転、拡大もあり、それらを変更すると、やはり見た目と当たり判定領域が一致しなくなりました。
移動よりは使わないかもしれませんが、地形のノードを回転・拡大する場合のことも考えて、Polygon2D ノードの回転・拡大の値も CollisionPolygon2D にコピーするようにしました。
node_collision_pollygon2d.scale = node_polygon2d.scale
node_collision_pollygon2d.rotation = node_polygon2d.rotation
以下は、Polygon2D ノードの移動・回転・拡大に対応したスクリプトです。
以下のスクリプトは Polygon2D と CollisionPolygon2D の上位ノードの StaticBody2D (リネーム後 Terrain ) ノードに割り当てます。
- StaticBody2D (ノード名 Terrain ) ←ここにスクリプトを割り当てます。
extends StaticBody2D
class_name Terrain
# 下位にある Polygon2D ノード
var node_polygon2d: Polygon2D
# 下位にある CollsionPollygon2D ノード
var node_collision_pollygon2d: CollisionPolygon2D
# Called when the node enters the scene tree for the first time.
func _ready():
# 下位にあるデフォルトの名前の2つのノードを取得します。
node_polygon2d = get_node("Polygon2D")
node_collision_pollygon2d = get_node("CollisionPolygon2D")
# Polygon2D の見た目のポリゴンのデータを当たり判定を行う CollisionPolygon2D にコピーします。
update_colission_polygon_2d()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
# Polygon2D のポリゴン情報などを CollisionPolygon2D にコピーします。
func update_colission_polygon_2d() -> void:
# 形を設定した Polygon2D ノードの polygon の情報を 当たり判定の領域として設定します。
node_collision_pollygon2d.polygon = node_polygon2d.polygon
node_collision_pollygon2d.position = node_polygon2d.position
node_collision_pollygon2d.scale = node_polygon2d.scale
node_collision_pollygon2d.rotation = node_polygon2d.rotation
テスト
F6 キーで現在のシーンを再生してテストすると、Polygon2D ノードを移動・回転・拡大したポリゴンの地形をキャラクターがのって移動できました。
変化するポリゴン用のフラグの追加
以下は AnimatableBody2D ノードを使った方が良いかもしれないので、推奨しません。
常に回転する地形などはまだ試していませんが、それに対応するために、物理演算のフレーム処理で毎回ポリゴンの情報をコピーするフラグと処理を追加してみました。
#動作を確認していませんので、参考程度にみてください。
以下のスクリプトは Polygon2D と CollisionPolygon2D の上位ノードの StaticBody2D (リネーム後 Terrain ) ノードに割り当てます。
extends StaticBody2D
class_name Terrain
# 下位にある Polygon2D ノード
var node_polygon2d: Polygon2D
# 下位にある CollsionPollygon2D ノード
var node_collision_pollygon2d: CollisionPolygon2D
# CollisionPolygon2D の当たり判定領域を毎フレーム Polygon2D からコピーします。変化する地形を想定しています。
var IsAlwaysUpdateCollisionPolygon2D: bool = false
# Called when the node enters the scene tree for the first time.
func _ready():
# 下位にあるデフォルトの名前の2つのノードを取得します。
node_polygon2d = get_node("Polygon2D")
node_collision_pollygon2d = get_node("CollisionPolygon2D")
# Polygon2D の見た目のポリゴンのデータを当たり判定を行う CollisionPolygon2D にコピーします。
update_colission_polygon_2d()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
# The engine calls this method before every physics step
func _physics_process(delta):
if IsAlwaysUpdateCollisionPolygon2D:
update_colission_polygon_2d()
func update_colission_polygon_2d() -> void:
# 形を設定した Polygon2D ノードの polygon の情報を 当たり判定の領域として設定します。
node_collision_pollygon2d.polygon = node_polygon2d.polygon
node_collision_pollygon2d.position = node_polygon2d.position
node_collision_pollygon2d.scale = node_polygon2d.scale
node_collision_pollygon2d.rotation = node_polygon2d.rotation
_physics_process イベント関数は、物理演算のフレーム処理で呼び出される関数です。
物理処理は、同様の仮想関数
アイドル処理と物理処理 — Godot Engine (4.x)の日本語のドキュメント_physics_process()
で動作します。これはゲーム世界に衝突判定を持つキャラクターの制御など、各物理ステップの前に実行する必要がある処理に使用します。前述のとおり、_physics_process()
は物理的な相互作用を安定させるために、可能な限り固定時間間隔(デフォルトでは毎秒60回)で呼び出されます。この間隔は、プロジェクト設定の Physics -> Common-> Physics Fps で変更できます。
まとめ
今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、 Polygon2D ノードのポリゴン情報を CollisionPolygon2D ノードにコピーして、見た目と当たり判定領域を一致させた前回のスクリプトでは、ノードの移動・回転・拡大に対応していなかったので、対応前の問題の確認と改善したスクリプトによる結果を紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Node2D — Godot Engine (4.x)の日本語のドキュメント
- StaticBody2D — Godot Engine (4.x)の日本語のドキュメント
- Polygon2D — Godot Engine (4.x)の日本語のドキュメント
- CollisionPolygon2D — Godot Engine (4.x)の日本語のドキュメント
- アイドル処理と物理処理 — Godot Engine (4.x)の日本語のドキュメント
記事一覧 → Compota-Soft-Press
コメント