概要
Godotでゲーム開発を始めたばかりのとき、プレイヤーキャラクターを動かそうとすると、CharacterBody2Dは最初の選択肢になるでしょう。しかし、move_and_slide()を呼び出しただけでは、キャラクターは奇妙な振る舞いをすることがあります。「ジャンプがおかしい」「壁に張り付いてしまう」「トップダウンなのに重力で落ちる」。これらの問題の多くは、CharacterBody2DのMotion Mode設定が原因です。
この記事では、CharacterBody2Dの2つの主要なMotion Mode、GroundedとFloatingの違いを解説します。それぞれのモードがどのようなゲームジャンルに最適で、どのように実装するのがベストプラクティスなのかを、具体的なコード例と共に紹介します。
Motion Modeとは
Motion Modeは、CharacterBody2Dが物理空間内でどのように振る舞うか、特に「床」「壁」「重力」をどう解釈するかを決定する、最も重要なプロパティです。インスペクタのCharacterBody2Dプロパティから設定でき、キャラクターの物理挙動の土台を定義します。
| モード (Mode) | 主な特徴 | 最適なゲームタイプ |
|---|---|---|
| Grounded | (接地モード) 重力の影響を受け、床・壁・天井を明確に区別します。is_on_floor()などの便利な床判定APIが利用可能です。 | 横スクロールプラットフォーマー、物理ベースのアクションゲーム |
| Floating | (浮遊モード) 重力を無視し、床という概念がありません。あらゆる方向からの衝突を等しく「壁」として扱います。 | トップダウン(見下ろし型) のRPG、シューティング、宇宙船ゲーム |
Grounded Mode: プラットフォーマー向け
Groundedは、その名の通り「地面に足がついた」キャラクターのためのモードです。マリオやメトロイドヴァニアのような、重力がゲームプレイの根幹をなすジャンルでは、ほぼ必須の選択肢となります。
主な特徴とメリット
- 自動的な重力適用: プロジェクト設定で定義された重力がキャラクターに作用します。
velocity.yに重力を加算するコードを書くだけで、自然な落下が実現できます。 - 信頼性の高い床判定:
is_on_floor()関数は、キャラクターが「床」として定義されたサーフェスに立っているかを正確に判定します。これにより、空中での無限ジャンプを簡単に防ぐことができます。 - 便利なAPI群:
is_on_wall()(壁接触)、is_on_ceiling()(天井接触)、get_floor_angle()(床の傾斜角度)など、プ ラットフォーマー開発を加速させる多くの便利な関数が用意されています。 - スムーズな坂道処理:
move_and_slide()は、キャラクターが坂道を滑らかに上り下りできるように、自動的に速度を調整してくれます。
実践的なコード例
以下は、基本的な移動、ジャンプ、そして壁ジャンプの要素を取り入れた、より実践的なGroundedモードのコードです。
@export var speed = 300.0
@export var jump_velocity = -400.0
@export var wall_jump_velocity = Vector2(400.0, -300.0)
# プロジェクト設定から重力を取得
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta):
# 重力を適用
if not is_on_floor():
velocity.y += gravity * delta
# ジャンプ処理
if Input.is_action_just_pressed("jump"):
if is_on_floor():
velocity.y = jump_velocity
elif is_on_wall():
# キャラクターが向いている方向と逆側に壁ジャンプ
var wall_normal = get_wall_normal()
velocity.x = wall_normal.x * wall_jump_velocity.x
velocity.y = wall_jump_velocity.y
# 左右移動
var direction = Input.get_axis("move_left", "move_right")
velocity.x = direction * speed
move_and_slide()
Floating Mode: トップダウン向け
Floatingモードは、キャラクターを重力から解放します。ゼルダの伝説のようなトップダウンRPGや、Vampire Survivorsのような全方位シューティングで、キャラクターがマップを自由に動き回る挙動に最適です。
主な特徴とメリット
- 重力からの解放: このモードでは重力が自動適用されません。
velocityがVector2.ZEROであれば、キャラクターはその場に静止します。 - 床の概念なし:
is_on_floor()は常にfalseを返します。全ての衝突は、方向に関わらず等しく扱われます。 - シンプルな移動ロジック: 重力や床の状態を考慮する必要がないため、移動ロジックが非常にシンプルになります。
実践的なコード例
8方向移動と、マウスカーソルの方向を向く機能を実装したFloatingモードのコードです。
@export var speed = 400.0
func _physics_process(delta):
# 入力から正規化された移動ベクトルを取得
var direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity = direction * speed
move_and_slide()
# マウスカーソルの方向を向く
look_at(get_global_mouse_position())
応用:慣性を持たせた滑らかな移動
宇宙船ゲームや氷上を滑るキャラクターなど、**慣性(入力を離しても滑り続ける動き)**を実装したい場合は、velocityを即座にゼロにせず、徐々に減衰させます。
@export var speed = 400.0
@export var friction = 0.05 # 摩擦係数(0に近いほど滑る)
func _physics_process(delta):
var direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
if direction != Vector2.ZERO:
# 入力がある場合は加速
velocity = velocity.lerp(direction * speed, 0.1)
else:
# 入力がない場合は徐々に減速(慣性)
velocity = velocity.lerp(Vector2.ZERO, friction)
move_and_slide()
frictionの値を調整することで、ツルツル滑る氷上からグリップの効く地面まで、様々な質感を表現できます。
代替パターンとの比較
単純なトップダウン移動では、CharacterBody2Dの代わりにArea2Dを使用するアプローチもあります。Area2Dは物理衝突を行わないため、非常に軽量です。敵の弾など、壁に当たって跳ね返る必要のないオブジェクトにはArea2Dが適している場合があります。しかし、壁との衝突応答が必要なプレイヤーや敵キャラクターには、CharacterBody2DのFloatingモードが堅牢で最適な選択です。
よくある間違いとベストプラクティス
Motion Modeを扱う上で陥りがちな罠と、それを避けるためのベストプラクティスをまとめました。
| よくある間違い | ベストプラ クティス |
|---|---|
| Groundedモードで重力を手動で加算し忘れる | _physics_process内で、is_on_floor()がfalseの時に必ずvelocity.yに重力を加算してください。 |
| トップダウンゲームでGroundedモードを使う | 重力が不要なゲームではFloatingモードを選択しましょう。コードがシンプルになり、意図しない落下を防げます。 |
is_on_floor()のチェックタイミングを誤解する | is_on_floor()はmove_and_slide()の実行によって更新されます。つまり、前フレームのmove_and_slide()で得られた接地状態を見ていることになります。ジャンプ入力を判定する際はmove_and_slide()の前でis_on_floor()をチェックし、その後move_and_slide()を呼び出すのが一般的なパターンです。 |
| パフォーマンスの過度な心配 | move_and_slide()は最適化されています。数百体のキャラクターを同時に動かすようなケースでない限り、パフォーマンスが問題になることは稀です。まずは正しく動作するコードを書きましょう。 |
まとめ
CharacterBody2DのMotion Modeは、単なる設定項目ではなく、ゲームの物理的な土台を定義する設計判断です。
- 横スクロールやプラットフォーマーで、重力と床が重要な役割を果たすなら → Grounded Mode
- トップダウンのRPGやシューティングで、自由な移動を実現したいなら → Floating Mode
最初にこの選択を正しく行うことで、キャラクター制御に関する多くの問題を未然に防ぎ、開発プロセスを効率化できます。
次のステップ
この記事でCharacterBody2Dの基本はマスターできました。さらに理解を深めるために、以下のトピックを探求することをお勧めします。
CharacterBody3D: 3D空間でのキャラクター制御。基本的な概念は2Dと共通しています。up_directionプロパティ: 重力の方向を変え、壁を歩くような特殊な動きを実装する方法。move_and_collide:move_and_slide()よりも低レベルな移動関数。衝突情報をより詳細に制御したい場合に使用します。