プレイヤー、箱、床、敵、動く足場。どれも衝突判定を持つオブジェクトですが、同じ物理ボディで作ると後から苦しくなります。
たとえばプレイヤーを RigidBody2D で作ると、物理的には自然に転がるかもしれませんが、入力にピタッと反応する操作感を作るのが難しくなります。逆に、物理パズルの箱を CharacterBody2D で作ると、重力や衝突による自然な動きを自分でかなり書くことになります。

この記事では、Godotの代表的な2D物理ボディを「誰が動きを決めるのか」という視点で整理します。
この記事でわかること
StaticBody2D、RigidBody2D、CharacterBody2Dの違い- プレイヤー、敵、箱、床、動く床でどれを選ぶべきか
move_and_slide()と力/インパルスの考え方の違い- 物理ボディ選びで起きやすい失敗
最初に選び方を決める
迷ったら、まず次の順に考えます。

| 質問 | 答え | 選びやすいノード |
|---|---|---|
| 動かない床、壁、障害物ですか? | はい | StaticBody2D |
| 重力や衝突で自然に動いてほしいですか? | はい | RigidBody2D |
| 入力やAIで狙った通りに動かしたいですか? | はい | CharacterBody2D |
| アニメーションやコードで動く床ですか? | はい | AnimatableBody2D |
大事なのは、「衝突するかどうか」ではなく 動きを誰が決めるか です。
- 動かない:
StaticBody2D - 物理エンジンが動かす:
RigidBody2D - 自分のコードが動かす:
CharacterBody2D - 動く床として、アニメーションやコードで動かす:
AnimatableBody2D
3つの中心は「誰が動かすか」
物理ボディはすべてCollisionShape2Dを持てますが、動き方の前提が違います。
| ノード | 動きの主体 | 代表例 | コードの考え方 |
|---|---|---|---|
StaticBody2D | 動かない | 床、壁、固定トゲ | 位置 は基本固定 |
RigidBody2D | 物理エンジン | 箱、ボール、落石 | 力やインパルスを与える |
CharacterBody2D | 開発者のコード | プレイヤー、敵、NPC | velocity を決めて move_and_slide() |

この違いを理解しないまま選ぶと、後からコードが複雑になります。プレイヤーをRigidBody2Dで作ると「押した瞬間に止まる」「空中制御を細かく調整する」「坂道で安定させる」といった処理が難しくなります。逆に、物理パズルの箱をCharacterBody2Dで作ると、押されたときの自然な転がりや反発を自分で再現する必要が出ます。
StaticBody2D: 動かない床や壁
StaticBody2D は、基本的に動かない物理ボディです。床、壁、固定された障害物のように、他のオブジェクトがぶつかる相手として使います。
Floor (StaticBody2D)
└─ CollisionShape2D
床や壁は、自分から動く必要がありません。プレイヤーや箱がぶつかったときに「ここから先へ進めない」という境界になれば十分です。
StaticBody2Dを使う場面は分かりやすいです。
- 地面
- 壁
- 固定された足場
- 動かないトゲ
- 押しても動かない障害物
注意点は、「動かないもの」に使うことです。毎フレーム position を変えて動かす足場をStaticBody2Dで作ると、接触しているキャラクターとの処理が不安定になりやすいです。動く足場には、後述する AnimatableBody2D を検討します。
RigidBody2D: 物理エンジンに任せる箱やボール
RigidBody2D は、重力、摩擦、衝突、反発などの物理シミュレーションで動くボディです。箱を押す、ボールが跳ねる、岩が転がる、物理パズルでブロックが倒れる、といった場面に向いています。
RigidBody2Dでは、毎フレーム position を直接書き換えるのではなく、力やインパルスを与えて動かします。
extends RigidBody2D
@export var launch_force: float = 600.0
func launch(direction: Vector2) -> void:
# 眠っているRigidBody2Dを起こしてから、衝撃を与える
sleeping = false
apply_central_impulse(direction.normalized() * launch_force)
このコードは、ボールや箱を一瞬で押し出す例です。apply_central_impulse() は「一瞬の衝撃」を与えるため、弾かれた箱や投げたボールのような動きに向いています。
RigidBody2Dを使うと、自然な物理挙動は作りやすいです。その代わり、「入力に対して毎回同じ距離だけ動く」「ボタンを離したら即停止する」のような精密制御は苦手です。
実装レシピ: 物理パズルの押せる箱
物理パズルで箱を使うなら 、次のように考えます。
- 箱を
RigidBody2Dにする CollisionShape2Dはできるだけ単純な長方形にする- 質量、摩擦、反発を調整する
- プレイヤーは
CharacterBody2Dにし、箱と衝突する - 箱が大量にある場合は、スリープや配置数を見直す
箱をコードで完全制御しようとするより、物理エンジンに任せた方が自然です。ただし数が増えるほど計算量も増えるため、物理演算が必要なものだけRigidBody2Dにします。
CharacterBody2D: コードで制御するプレイヤーや敵
CharacterBody2D は、プレイヤーや敵のように、ゲーム側のロジックで動かしたいキャラクターに使います。
物理エンジンに完全に任せるのではなく、開発者が velocity を決め、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():
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
# CharacterBody2Dはmove_and_slideで移動と衝突をまとめて処理する
move_and_slide()
プレイヤーや敵には、ほとんどの場合 CharacterBody2D が向いています。理由は、ゲームの操作感をコードで細かく決められるからです。
- 入力した瞬間に加速したい
- 空中制御を調整したい
- 坂道で滑らないようにしたい
- ノックバックや攻撃硬直を状態ごとに変えたい
- AIで目的地へ向かわせたい
こうした処理は、物理エンジン任せよりもコードで制御した方が作りやすいです。
実制作での使い分け
ゲームオブジェクトごとに見ると、選び方はかなり整理できます。

| オブジェクト | おすすめ | 理由 |
|---|---|---|
| プレイヤー | CharacterBody2D | 入力に対して狙った通りに動かしたい |
| 敵 | CharacterBody2D | AIや状態管理で動きを制御したい |
| ボール | RigidBody2D | 反発、重力、衝突を自然に扱いたい |
| 押せる箱 | RigidBody2D | 他の物体との押し合いを物理に任せたい |
| 床、壁 | StaticBody2D | 動かず、衝突の境界になればよい |
| 動く床 | AnimatableBody2D | 動く足場として、物理更新と合わせて扱い たい |
| 攻撃範囲 | Area2D | 衝突で止めるより、入った/出たを検出したい |
Area2D は物理ボディではありませんが、混同しやすいので表に入れました。攻撃判定、アイテム取得範囲、センサーのように「重ならないように止める」必要がなく、「入ったことを検出したい」だけなら Area2D が向いています。
よくあるつまずき
プレイヤーをRigidBody2Dで作って操作感が暴れる
RigidBody2Dは物理シミュレーションが主役です。慣性、摩擦、反発の影響を受けるため、プレイヤーを思った通りに止める、ジャンプ高さを安定させる、坂道で自然に動かす、といった調整が難しくなります。
物理そのものが主役のゲームでない限り、プレイヤーや敵は CharacterBody2D から始めるのが安全です。
CharacterBody2Dのpositionを直接変える
CharacterBody2D を position += ... で動かすと、move_and_slide() による衝突処理を飛ばしてしまいます。結果として壁抜けや押し戻しの不自然さにつながります。
基本は velocity を更新し、最後に move_and_slide() を呼びます。
StaticBody2Dを毎フレーム動かす
StaticBody2Dは「動かないもの」として使うのが基本です。動く足場を作りたい場合は AnimatableBody2D を検討します。
もちろん、小さなプロトタイプではStaticBody2Dを動かしても動くことがあります。ただし、接触しているキャラクターを正しく運ぶ、物理更新と同期する、といった部分で詰まりやすくなります。
CollisionShape2Dを複雑にしすぎる
衝突形状が複雑になるほど、物理計算も調整も難しくなります。特にRigidBody2Dを大量に使う場合は、できるだけ単純な RectangleShape2D や CircleShape2D から始めるのがおすすめです。
おまけ: 先に知っておくと良いこと
動く床は別枠で考える
動く床は、床のようにプレイヤーを支えますが、位置は変わります。そのため、単純なStaticBody2Dとも、自然に転がるRigidBody2Dとも違う性質です。
Godotでは AnimatableBody2D が候補になります。アニメーションやコードで動かしつつ、他の物理ボディとの接触を扱うためのノードです。プラットフォーマーでエレベーター、左右に動く足場、ベルトコンベア風の床を作るときに調べる価値があります。
Area2Dは「ぶつかって止める」ためのものではない
攻撃範囲やアイテム取得範囲には Area2D を使うことが多いです。Area2Dは重なりを検出するためのノードで、床や壁のように進行を止める物理ボディとは役割が違います。
「触れたら反応したい」のか、「ぶつかって止めたい」のかを分けると、Area2Dと物理ボディの選択で迷いにくくなります。
物理処理は_physics_processに寄せる
CharacterBody2D の移動、RigidBody2Dへの力の適用、物理状態の読み取りは、基本的に _physics_process() 側で考えると安定します。
見た目の演出やUI更新は _process() でも構いませんが、物理ボディの動きそのものは物理更新に合わせるのが基本です。
まとめ
StaticBody2Dは、動かない床や壁に使うRigidBody2Dは、箱やボールのように物理エンジンへ動きを任せたいものに使うCharacterBody2Dは、プレイヤーや敵のようにコードで精密に動かしたいものに使うAnimatableBody2Dは、動く床やエレベーターの候補になる- 「衝突するか」ではなく、「誰が動きを決めるか」で選ぶ
物理ボディ選びは、後からの作りやすさに直結します。最初に正しいノードを選ぶだけで、操作感の調整、バグ調査、パフォーマンス管理がかなり楽になります。