Godot Engineで使用するノードに関しての備忘録です。
この記事はGeminiを活用して作成しました。
はじめに
Godot Engine 4で2DのアクションゲームやRPGを作る際、プレイヤーや敵キャラクターの移動・壁との衝突判定にほぼ100%使うのが CharacterBody2D ノードです
この記事では、CharacterBody2D の基本的な仕組みから、Godot 4で推奨される移動テンプレートコードの解説、よくあるトラブルの解決法までをまとめます
1. CharacterBody2Dとは?
Godotの2D物理ボディノードの一つで、「スクリプト(コード)で制御できる物理ボディ」 です
他のノードとの違い(ざっくり比較)
- StaticBody2D: 壁や床など、動かないオブジェクト用
- RigidBody2D: 物理エンジン(重力や摩擦など)に挙動を完全に任せるオブジェクト用
- CharacterBody2D: プレイヤーや敵など、「重力は受けてほしいけれど、ジャンプ力や移動速度はコードで細かく制御したい」 オブジェクト用
2. 基本的なノード構成
CharacterBody2D は単体では動作しません。エディタ上で以下のようにノードを組み合わせるのが基本の形です
- 📁 CharacterBody2D <--スクリプトをアタッチして移動を制御
- 📄 Sprite2D または AnimatedSprite2D <--見た目を表示
- 📄 CollisionShape2D <--当たり判定の形を設定
⚠️ 注意
CollisionShape2Dを追加しても「Shape(形状)」を設定しないと、壁や床をすり抜けてしまいます。インスペクターから必ず新規 RectangleShape2Dなどを指定してください
3. スクリプト(GDScript)での移動実装
CharacterBody2D ノードにスクリプトを新規作成すると、2D横スクロールアクション用の基本コードが自動生成されます(テンプレートから 「Character Body 2D: Basic Movement」 を選択)
このコードの主要な部分を解剖して解説します
extends CharacterBody2D
# 移動速度とジャンプ力の定義
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _physics_process(delta: float) -> void:
# 1. 重力の適用(床にいない場合のみ)
if not is_on_floor():
velocity += get_gravity() * delta
# 2. ジャンプ入力の処理
if input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# 3. 左右の入力方向を取得(-1, 0, 1 のいずれかが返る)
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
# 入力がない場合は減速(摩擦の表現)
velocity.x = move_toward(velocity.x, 0, SPEED)
# 4. 超重要:実際に移動させる関数
move_and_slide()
💡 押さえておきたい Godot 4 のポイント
変数 velocity
Godot 3までは移動関数に速度を渡す必要がありましたが、Godot 4ではノード自体が velocity(Vector2型) という速度プロパティを持っています。この velocity を書き換えてから move_and_slide() を呼ぶだけで移動します
move_and_slide() の仕様変更
引数が不要になりました。この関数を呼ぶと、自動的に velocity を元に移動し、壁や坂道にぶつかると滑らかに滑る(スライドする)移動処理を行ってくれます。さらに、内部で delta(経過時間)を自動計算してくれるため、手動で * delta を掛ける必要はありません(※重力計算など、速度の加算時のみ delta が必要です)
床判定関数
move_and_slide() を実行した直後、以下の便利な判定関数が使えるようになります
-
is_on_floor(): 床に接地しているか(ジャンプの可否判定に便利) -
is_on_wall(): 壁にぶつかっているか -
is_on_ceiling(): 天井に頭をぶつけているか
4. トップダウン(全方位)移動にする場合
RPGや全方位シューティングのような「重力がない真上視点」のゲームにする場合は、コードを以下のように書き換えます
extends CharacterBody2D
const SPEED = 300.0
func _physics_process(delta: float) -> void:
# 上下左右の入力を Vector2 として一括取得
var direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if direction:
velocity = direction * SPEED
else:
# 入力がなければスムーズに停止
velocity = velocity.move_toward(Vector2.ZERO, SPEED)
move_and_slide()
5. よくあるトラブルと対策
Q. 壁にぶつかったときにガタガタ震える・めり込む
-
原因: 独自の計算で
position(座標)を直接書き換えて移動させていませんか? -
対策:
position += velocityのような直接書き換えは物理衝突を無視します。必ずvelocityを設定してmove_and_slide()で移動させるようにしてください
Q. 坂道を上るときに滑り落ちてしまう
-
対策:
CharacterBody2DのインスペクターにあるFloor Block On WallやFloor Constant Speedをオンにすると、坂道でも滑らずに一定速度で進めるようになります
まとめ
CharacterBody2D は、「velocity を書き換えて move_and_slide() を呼ぶ」 という基本さえマスターすれば、あらゆる2Dキャラクターの動きに応用可能です
アニメーションを制御する AnimatedSprite2D と組み合わせることで、一気にゲームらしい挙動が作れるようになるので、ぜひ色々な移動を試してみてください!
参考リンク