【Godot】CharacterBody2DのMotion Mode:トップダウンと横スクロールの使い分け

作成: 2025-06-20最終更新: 2025-12-16

CharacterBody2DのGroundedとFloatingモードの違いを解説。トップダウンと横スクロールでの最適な使い分け、コード例、よくある間違いとベストプラクティスを紹介します。

概要

Godotでゲーム開発を始めたばかりのとき、プレイヤーキャラクターを動かそうとすると、CharacterBody2Dは最初の選択肢になるでしょう。しかし、move_and_slide()を呼び出しただけでは、キャラクターは奇妙な振る舞いをすることがあります。「ジャンプがおかしい」「壁に張り付いてしまう」「トップダウンなのに重力で落ちる」。これらの問題の多くは、CharacterBody2DMotion Mode設定が原因です。

この記事では、CharacterBody2Dの2つの主要なMotion Mode、GroundedFloatingの違いを解説します。それぞれのモードがどのようなゲームジャンルに最適で、どのように実装するのがベストプラクティスなのかを、具体的なコード例と共に紹介します。

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のような全方位シューティングで、キャラクターがマップを自由に動き回る挙動に最適です。

主な特徴とメリット

  • 重力からの解放: このモードでは重力が自動適用されません。velocityVector2.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が適している場合があります。しかし、壁との衝突応答が必要なプレイヤーや敵キャラクターには、CharacterBody2DFloatingモードが堅牢で最適な選択です。


よくある間違いとベストプラクティス

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()よりも低レベルな移動関数。衝突情報をより詳細に制御したい場合に使用します。