【Godot】CharacterBody2DのMotion Mode

作成: 2025-06-20最終更新: 2026-07-07

GodotのCharacterBody2DにあるGrounded/Floating Motion Modeを、プラットフォーマー、メトロイドヴァニア、トップダウンRPG、ツインスティックシューターの例で使い分けます。

前の記事で、プレイヤーや敵のようにコードで動きを制御したいキャラクターには CharacterBody2D が向いている、と整理しました。

では、CharacterBody2D を選んだあと、インスペクタにある Motion Mode はどう選べばよいのでしょうか。ここを間違えると、横スクロールなのに床判定が不安定になったり、トップダウンなのに床や重力の考え方を持ち込んでコードが複雑になったりします。

Groundedは床とジャンプ、Floatingはトップダウン全方向移動に向くことを示す図

この記事でわかること

  • GroundedFloating の違い
  • Motion Modeが「重力のON/OFF」ではない理由
  • プラットフォーマーとトップダウンでコードがどう変わるか
  • is_on_floor()up_directionmove_and_slide() の関係

Sponsored

Motion Modeは衝突面の解釈を決める

Motion Modeは、ざっくり言うと move_and_slide() が衝突した面をどう扱うかを決める設定です。

Grounded では、衝突した面を 天井 として区別します。is_on_floor()is_on_wall()is_on_ceiling() のような判定を使いやすくなります。

Floating では、床という考え方を基本的に使いません。トップダウンゲームのように、上下左右どの方向にも同じように移動し、衝突はだいたい「壁」として扱いたい場面に向いています。

Groundedでは床・壁・天井を区別し、Floatingでは周囲の衝突を壁として扱う図

重要なのは、Groundedにしただけで重力が自動適用されるわけではない ことです。CharacterBody2DはRigidBody2Dのように物理エンジンへ動きを任せるノードではありません。落下させたいなら、コードで velocity.y に重力を足します。

if not is_on_floor():
    # 重力はMotion Modeではなく、コードで加算する
    velocity.y += gravity * delta

Motion Modeは「重力をかけるか」ではなく、「衝突した面を床として扱うか、壁として扱うか」に近い設定だと考えると混乱しにくいです。

設定場所

Motion Modeは、CharacterBody2D を選択した状態でインスペクタから変更できます。

CharacterBody2DのMotion Mode設定画面

スクリプトから設定することもできます。

func _ready() -> void:
    # プラットフォーマー向け
    motion_mode = CharacterBody2D.MOTION_MODE_GROUNDED

    # トップダウン向けにするならこちら
    # motion_mode = CharacterBody2D.MOTION_MODE_FLOATING

ただし、通常はインスペクタで設定しておけば十分です。記事内のコードでは分かりやすさのために明示することがありますが、実制作ではキャラクターシーンごとにインスペクタで決める方が見通しが良い場合も多いです。

Sponsored

Grounded: 床とジャンプがあるゲーム

Grounded は、床に立つ、ジャンプする、坂道を歩く、壁にぶつかる、といった横スクロール系のゲームに向いています。

代表例は次の通りです。

  • 2Dプラットフォーマー
  • メトロイドヴァニア
  • 横スクロールアクション
  • 重力と床が重要なアクションRPG

基本コードは、重力、ジャンプ、左右移動、move_and_slide() の順に考えます。

extends CharacterBody2D

const SPEED := 260.0
const JUMP_VELOCITY := -420.0

var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")

func _physics_process(delta: float) -> void:
    if not is_on_floor():
        # Groundedでも、重力は自分でvelocityへ足す
        velocity.y += gravity * delta

    if Input.is_action_just_pressed("jump") and is_on_floor():
        # 床にいるときだけジャンプを許可する
        velocity.y = JUMP_VELOCITY

    var direction := Input.get_axis("move_left", "move_right")
    velocity.x = direction * SPEED

    # ここで移動し、床/壁/天井の接触状態が更新される
    move_and_slide()

is_on_floor() は、直前の move_and_slide() の結果をもとに更新されます。多くのプレイヤー制御では、上のように _physics_process() 内で接地状態を見てジャンプを決め、最後に move_and_slide() を呼びます。

実装レシピ: プラットフォーマーのプレイヤー

プラットフォーマーなら、次の順番で組むと整理しやすいです。

  1. CharacterBody2D のMotion Modeを Grounded にする
  2. velocity.y に重力を加算する
  3. is_on_floor() のときだけジャンプを許可する
  4. 左右入力で velocity.x を決める
  5. 最後に move_and_slide() を呼ぶ

この形にしておくと、次の段階で可変ジャンプ、コヨーテタイム、ジャンプバッファ、坂道調整を足しやすくなります。床判定が設計の中心になるゲームなら、Groundedから始めるのが自然です。

Floating: 床の概念がいらないゲーム

Floating は、トップダウンゲームのように床や天井を区別しないキャラクターに向いています。

代表例は次の通りです。

  • トップダウンRPG
  • 見下ろし型アクション
  • ツインスティックシューター
  • 宇宙船の全方向移動

トップダウンでは、重力や is_on_floor() を考えるより、上下左右の入力から移動ベクトルを作る方がシンプルです。

extends CharacterBody2D

const SPEED := 220.0

func _ready() -> void:
    motion_mode = CharacterBody2D.MOTION_MODE_FLOATING

func _physics_process(delta: float) -> void:
    # 上下左右の入力を1つの方向ベクトルにする
    var input_vector := Input.get_vector(
        "move_left",
        "move_right",
        "move_up",
        "move_down"
    )

    velocity = input_vector * SPEED

    # Floatingでは床判定より、壁との衝突で止まることが主役
    move_and_slide()

このコードには重力もジャンプもありません。プレイヤーは上下左右に動き、壁にぶつかれば止まります。

実装レシピ: トップダウンRPGのプレイヤー

トップダウンRPGなら、次のように考えます。

  1. Motion Modeを Floating にする
  2. InputMapに move_left/right/up/down を用意する
  3. Input.get_vector() で移動方向を作る
  4. velocity = input_vector * speed で速度を決める
  5. move_and_slide() で壁との衝突を処理する

この形なら、上下左右の移動、斜め移動、ゲームパッド対応をまとめて扱えます。床判定を持ち込まないため、横スクロール用のジャンプコードが混ざらず、読みやすくなります。

Sponsored

ジャンル別の選び方

ゲームジャンルで見ると、Motion Modeの選択はかなり分かりやすくなります。

横スクロールと探索アクションはGrounded、見下ろしRPGと全方位シューティングはFloatingを使う図
ジャンル基本の選択理由
プラットフォーマーGrounded床、ジャンプ、落下、坂道が重要
メトロイドヴァニアGrounded壁、床、天井、ジャンプ制御を使う
トップダウンRPGFloating床判定より上下左右移動が重要
ツインスティックシューターFloating移動方向と照準方向を自由に扱う
宇宙船ゲームFloating重力に縛られない全方向移動に向く

迷ったら「ジャンプと床判定がゲームの中心か?」で判断します。中心なら Grounded、中心でないなら Floating を先に試すとよいです。

コード構造の違い

GroundedとFloatingの違いは、コードの流れにも出ます。

Groundedの処理は重力、is_on_floor、ジャンプ、move_and_slideで構成され、Floatingの処理はInput.get_vector、velocity、move_and_slideで構成される図

Groundedでは、縦方向の状態管理が増えます。

  • 重力を足す
  • 床にいるか確認する
  • ジャンプできるか判断する
  • 天井や坂道を考える

Floatingでは、移動方向の計算が中心です。

  • 上下左右入力を読む
  • 速度ベクトルを作る
  • 壁との衝突で止める
  • 必要なら照準や向きを別で処理する

この違いを最初に分けておくと、トップダウン用のコードに is_on_floor() が混ざったり、横スクロール用のコードに不要な全方向移動処理が混ざったりしにくくなります。

Sponsored

よくあるつまずき

Groundedにしたのに落下しない

Groundedは「重力を自動でかける設定」ではありません。落下しない場合は、velocity.y += gravity * delta のように重力をコードで足しているか確認してください。

トップダウンなのにis_on_floorを見ている

トップダウンでは、床に立っているかどうかをゲームロジックで使わないことがほとんどです。is_on_floor() に頼る設計になっているなら、横スクロール用の考え方が混ざっている可能性があります。

トップダウンでは、壁にぶつかったか、敵やアイテムに触れたか、攻撃範囲に入ったか、のような判定が中心です。必要なら Area2D やRayCast2Dも組み合わせます。

Floatingなら何でもすり抜けると思っている

Floatingでも、CollisionShape2DやCollision Layer/Maskが正しく設定されていれば、move_and_slide() で壁との衝突を処理できます。

すり抜ける場合は、Motion Modeより先に次を確認します。

  • CollisionShape2D があるか
  • レイヤーとマスクが合っているか
  • move_and_slide() を呼んでいるか
  • position を直接書き換えていないか

Motion Modeを途中で切り替えすぎる

特殊なゲームでは、通常時はGrounded、水中や宇宙空間ではFloatingのように切り替えることもあります。ただし、初心者のうちは複雑になりやすいです。

モードを切り替えるなら、重力、入力、ジャンプ、摩擦、アニメーションも一緒に切り替える必要があります。単に motion_mode だけ変えても、操作感が自然になるとは限りません。

おまけ: 先に知っておくと良いこと

up_directionは「どちらが上か」を決める

Groundedでは、up_direction が床/壁/天井の判定に関係します。通常の2Dゲームでは Vector2.UP のままで問題ありません。

壁を歩くゲーム、重力方向が変わるゲーム、惑星の表面を歩くゲームでは、この設定が重要になります。ただし通常のプラットフォーマーでは、まずデフォルトで安定した移動を作る方が先です。

floor_snap_lengthは足元の安定に関係する

Groundedでは、坂道や段差で床から一瞬離れたように見えることがあります。floor_snap_length は、床へ吸い付くような挙動に関係します。

この値を調整すると、坂道や下り坂での接地が安定する場合があります。ただし、最初から細かく触るより、基本の重力・ジャンプ・CollisionShape2Dが正しいかを先に確認してください。

Area2Dとの役割は別

トップダウンゲームでは、プレイヤー本体を CharacterBody2D のFloatingにし、攻撃範囲やアイテム取得判定を Area2D にする構成がよくあります。

CharacterBody2D は「移動して壁にぶつかる本体」、Area2D は「触れたことを検出する範囲」と分けると、責務がきれいになります。

まとめ

  • Grounded は、床、壁、天井を区別したい横スクロール向け
  • Floating は、床の概念がいらないトップダウンや全方向移動向け
  • Motion Modeは重力の自動ON/OFFではなく、move_and_slide() の衝突解釈に関係する
  • Groundedでも重力はコードで velocity へ加算する
  • トップダウンでは Input.get_vector() とFloatingの組み合わせがシンプル

判断に迷ったら、「このゲームでジャンプと床判定は中心的な仕組みか?」と考えてください。中心ならGrounded、そうでなければFloatingから始めると整理しやすくなります。

さらに学ぶために