無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 では、CharacterBody2D クラスを使うことで簡単に左右に移動したりジャンプする挙動を実装できます。
そのために自動的に作られるスケルトンコードがどのように、その動きを実現しているのか、スクリプトの処理について紹介します。
※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※紹介するスクリプトは自己責任でお使いください。
関連記事
前回までの3話で、AnimatableBody2D ノードなどを使って指定した位置を往復する動く地形を作りました。
以前の記事では、 2D の左右移動やジャンプ移動ができる CharacterBody2D クラスを使って、操作するキャラクターを作成する手順を紹介しました。
CharacterBody2D のスケルトンコード
スケルトンコードは、シーンドックで CharacterBody2D ノードを選択して、右上の+マークのついた「選択したノードに新規または既存のスクリプトをアタッチする。」ボタンを押したあと、「ノードにスクリプトをアタッチする」ダイアログでパスを確認して「作成」ボタンを押すと作られます。
※下図の GodotSan は CharacterBody2D ノードをリネームしたものです。
Script ワークスペースで、作成したスクリプトを左側のリストから選択すると以下のようなスケルトンコードが CharacterBody2D の場合は作られます。
このスクリプトだけで、落下、着地、左右移動、ジャンプが実装されています。
extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
定数の意味
CharacterBody2D のスケルトンコードでは、2つの定数が宣言され、処理で使われています。
GD スクリプトでは定数を const で定義します。
var による変数と異なり、値をあとで変更できません。
定数
定数はゲームの実行中に変更することができない値のことです。これらの値はコンパイル時に確定している必要があります。
const
キーワードを使うことで定数に名前を付けることができます。定数を宣言したよりも後に値を代入しようとすると、エラーが発生します。値を変更するつもりがないのなら、定数を用いることを推奨します。
GDScriptリファレンス — Godot Engine (4.x)の日本語のドキュメント
スケルトンコードでは、左右へ移動する際の加速度 SPEED と、ジャンプ時に上方向(重力の反対方向)への加速度 JUMP_VELOCITY が定数として使われています。
これらをゲーム中に変化させたい場合は var で変数に置き換えると良いでしょう。
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
_physics_process 関数内の処理
以下は、物理演算のフレーム処理を行う _physics_process イベント関数内の処理を3つに分けて処理される順番に紹介します。
引数の delta は前回の同イベント関数を呼び出した後の経過時間です。
物理処理は、同様の仮想関数
アイドル処理と物理処理 — Godot Engine (4.x)の日本語のドキュメント_physics_process()
で動作します。これはゲーム世界に衝突判定を持つキャラクターの制御など、各物理ステップの前に実行する必要がある処理に使用します。前述のとおり、_physics_process()
は物理的な相互作用を安定させるために、可能な限り固定時間間隔(デフォルトでは毎秒60回)で呼び出されます。この間隔は、プロジェクト設定の Physics -> Common-> Physics Fps で変更できます。
落下
is_on_floor 関数で、 false の場合、つまり着地していない空中にいる状態の場合に、重力のベクトルと同じ方向に、経過時間 (delta) 分の加速度を加えて、落下させます。
※ Input.get_gravity() ではなく PhysicsBody2D.get_gravity() です。
※ is_on_floor 関数で着地しているか判定できるのは素晴らしい!
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
Returns the gravity vector computed from all sources that can affect the body, including all gravity overrides from Area2D nodes and the global world gravity.
Area2D ノードおよびグローバル ワールド重力からのすべての重力オーバーライドを含む、ボディに影響を与える可能性のあるすべてのソースから計算された重力ベクトルを返します。PhysicsBody2D — Godot Engine (4.x)の日本語のドキュメント get-gravity
ジャンプ
ジャンプ( ui_accept アクション)の入力があった際に、着地していれば、定数で指定した加速度を上方向に設定して、キャラクターを上方向に加速させます。
※ ui_accept アクションはスペースキーなどに対応していて、最初からプロジェクト設定に割り当てられています。
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
左右移動と入力がない場合の減速
左右移動の入力があれば、その方向に SPEED 定数でキャラクターを加速させます。
入力がない場合は、move_toward 関数で SPEED を上限として横方向の加速度を 0 に近づけて、減速して止まるようにします。
例えば、move_toward の処理で、横方向の加速度が 10 で、SPEED が 2 の場合、1回の処理では上限の 2 だけ 0 に近づけるので、 8, 6, 4, 2, 0 と 5 回の physics_process で入力がない場合にキャラクターが止まり、それまでは少し滑ったような動きをします。
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
Input.get_axis は指定した二つのアクション(左右など相反する入力)を比較して、左右どちらの入力が大きいかを +, – の値で教えてくれます。
0 の場合は、指定したアクションの入力がないことを表し、続きの if 文では else の処理がそれにあたります。
Get axis input by specifying two actions, one negative and one positive.
This is a shorthand for writing
Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")
.2 つのアクション (負のアクションと正のアクション) を指定して軸入力を取得します。Input — Godot Engine (4.x)の日本語のドキュメント
move_toward(a, b, c) は a の値を c を上限にして b に近づけた値を返します。
※以下の引用は Vector2 版です。
Returns a new vector moved toward
to
by the fixeddelta
amount. Will not go past the final value.固定デルタ量だけ に向かって移動した新しいベクトルを返します。最終値を超えることはありません。
Vector2 — Godot Engine (4.x)の日本語のドキュメント
設定した加速度で移動させて衝突の相互作用を行う
今まで設定してきたキャラクターの加速度 velocity メンバ変数をもとに、実際に移動させて衝突などを行います。
RigidBody2D と異なり、衝突した後の相互作用は行わず、単純に壁にぶつかったらとまるなど、衝突の後の処理は簡素化されているので、2D ゲームの挙動に近い動きを実現してくれます。
move_and_slide
Using CharacterBody2D/3D — Godot Engine (4.x)の日本語のドキュメント
move_and_slide()
メソッドは、一方のボディをもう一方のボディに沿ってスライドさせたいという一般的なケースで衝突応答を単純化することを目的としています。 たとえば、プラットフォーマーやトップダウンゲームで特に役立ちます。
まとめ
今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 では、簡単に左右に移動したりジャンプする挙動を実装できる CharacterBody2D クラスのスケルトンコードがどのように、その動きを実現しているのか、スクリプトの処理について紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Godot 4 Moving Platforms – YouTube
- Using CharacterBody2D/3D — Godot Engine (4.x)の日本語のドキュメント
- CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント
- Sprite2D — Godot Engine (4.x)の日本語のドキュメント
- CollisionShape2D — Godot Engine (4.x)の日本語のドキュメント
- Input — Godot Engine (4.x)の日本語のドキュメント #get-axis
- Vector2 — Godot Engine (4.x)の日本語のドキュメント #move-toward
- GDScriptリファレンス — Godot Engine (4.x)の日本語のドキュメント
- アイドル処理と物理処理 — Godot Engine (4.x)の日本語のドキュメント
- PhysicsBody2D — Godot Engine (4.x)の日本語のドキュメント get-gravity
記事一覧 → Compota-Soft-Press
コメント