1. Introduction 1. はじめに
Godot 4 introduced major changes to character movement. The old KinematicBody2D and KinematicBody3D nodes were renamed to CharacterBody2D and CharacterBody3D, and the move_and_slide() API was completely redesigned. If you're migrating from Godot 3 or starting fresh, this guide covers everything you need to know.
Godot 4ではキャラクター移動に大きな変更が加えられました。旧KinematicBody2DとKinematicBody3DノードはCharacterBody2DとCharacterBody3Dに改名され、move_and_slide() APIは完全に再設計されました。Godot 3からの移行でも、新規開始でも、このガイドで必要な情報を全てカバーします。
CharacterBody2D and CharacterBody3D are physics bodies designed for characters controlled by code. Unlike RigidBody, they don't respond to forces automatically — you control their movement entirely through script. This makes them ideal for player characters, NPCs, and anything that needs precise, deterministic movement.
CharacterBody2DとCharacterBody3Dはコードで制御されるキャラクター用の物理ボディです。RigidBodyとは異なり、力に自動的に反応せず、移動はすべてスクリプトで制御します。そのため、プレイヤーキャラクター、NPC、そして正確で決定論的な動きが必要なすべてのものに最適です。
2. What Changed from Godot 3 2. Godot 3からの変更点
Here are the most important changes between Godot 3 and Godot 4 for character movement:
Godot 3からGodot 4でのキャラクター移動における主要な変更点は以下の通りです:
-
KinematicBody2Dis nowCharacterBody2DKinematicBody2DがCharacterBody2Dに変更 -
KinematicBody3Dis nowCharacterBody3DKinematicBody3DがCharacterBody3Dに変更 -
velocityis now a built-in property — you no longer pass it tomove_and_slide()velocityは組み込みプロパティになりました —move_and_slide()に渡す必要はありません -
move_and_slide()takes no arguments — it reads directly from thevelocitypropertymove_and_slide()は引数なしになりました —velocityプロパティから直接読み取ります -
move_and_slide_with_snap()is removed — use thefloor_snap_lengthproperty insteadmove_and_slide_with_snap()は削除されました — 代わりにfloor_snap_lengthプロパティを使用 -
is_on_floor(),is_on_wall(),is_on_ceiling()still work the same wayis_on_floor()、is_on_wall()、is_on_ceiling()は従来通り動作します -
get_gravity()was added in Godot 4.4 to read the project's default gravity as a Vector — very convenientget_gravity()がGodot 4.4で追加され、プロジェクトのデフォルト重力をVectorとして取得できるようになりました
In Godot 3, move_and_slide() returned the resulting velocity. In Godot 4, it returns a bool (whether a collision occurred), and the velocity is updated in-place on the velocity property.
Godot 3ではmove_and_slide()は結果の速度を返していました。Godot 4ではbool(衝突が発生したかどうか)を返し、velocityはvelocityプロパティ上で直接更新されます。
3. Basic 2D Platformer Controller 3. 基本的な2Dプラットフォーマーコントローラー
This is the standard side-scrolling platformer controller. The character can move left/right and jump when on the ground. This is the template Godot generates when you create a new CharacterBody2D script.
これは標準的な横スクロールプラットフォーマーコントローラーです。キャラクターは左右に移動し、地面にいるときにジャンプできます。これはGodotが新しいCharacterBody2Dスクリプトを作成する際に生成するテンプレートです。
extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _physics_process(delta: float) -> void:
# Apply gravity when not on floor
if not is_on_floor():
velocity += get_gravity() * delta
# Jump when on floor and jump pressed
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Horizontal movement
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
Line-by-line Breakdown
1行ずつの解説
-
extends CharacterBody2D— The script inherits from CharacterBody2D, giving us access tovelocity,move_and_slide(),is_on_floor(), etc.extends CharacterBody2D— CharacterBody2Dを継承し、velocity、move_and_slide()、is_on_floor()等にアクセスできます。 -
SPEED = 300.0— Horizontal movement speed in pixels per second.SPEED = 300.0— 水平方向の移動速度(ピクセル/秒)。 -
JUMP_VELOCITY = -400.0— Negative because Y-axis points downward in 2D. A negative value moves the character upward.JUMP_VELOCITY = -400.0— 2DではY軸が下向きなので負の値。負の値でキャラクターが上方向に移動します。 -
get_gravity() * delta— Applies project gravity each frame.get_gravity()returns aVector2pointing downward (e.g.,Vector2(0, 980)). Multiplying bydeltamakes it frame-rate independent.get_gravity() * delta— 毎フレーム重力を適用します。get_gravity()は下向きのVector2(例:Vector2(0, 980))を返します。deltaを掛けることでフレームレートに依存しなくなります。 -
Input.get_axis("ui_left", "ui_right")— Returns a float from -1.0 to 1.0 based on which direction key is pressed. Supports analog input.Input.get_axis("ui_left", "ui_right")— 押されている方向キーに応じて-1.0から1.0のfloatを返します。アナログ入力にも対応。 -
move_toward(velocity.x, 0, SPEED)— Smoothly decelerates to zero when no input is pressed. The third argument is the maximum change per call.move_toward(velocity.x, 0, SPEED)— 入力がないとき滑らかにゼロまで減速します。3番目の引数は1回の呼び出しでの最大変化量です。 -
move_and_slide()— Moves the body using the currentvelocity, handles collisions, slides along surfaces, and updatesvelocityautomatically.move_and_slide()— 現在のvelocityを使ってボディを移動し、衝突を処理し、面に沿ってスライドし、velocityを自動的に更新します。
Your CharacterBody2D needs at least one CollisionShape2D child node with a shape assigned (e.g., RectangleShape2D or CapsuleShape2D). Without it, move_and_slide() won't detect any collisions.
CharacterBody2Dには少なくとも1つのCollisionShape2D子ノードに形状(RectangleShape2DやCapsuleShape2D等)を設定する必要があります。これがないとmove_and_slide()は衝突を検出しません。
4. Basic 2D Top-Down Controller 4. 基本的な2Dトップダウンコントローラー
For top-down games (RPGs, twin-stick shooters, etc.), you move in all four directions without gravity. The code is simpler than a platformer.
トップダウンゲーム(RPG、ツインスティックシューター等)では、重力なしで4方向に移動します。プラットフォーマーよりコードはシンプルです。
extends CharacterBody2D
const SPEED = 200.0
func _physics_process(delta: float) -> void:
var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = input_direction * SPEED
move_and_slide()
How It Works
仕組み
-
Input.get_vector()returns a normalizedVector2from four input actions. This handles diagonal movement correctly — the vector's length is always 1.0 or 0.0, so diagonal movement isn't faster than cardinal movement.Input.get_vector()は4つの入力アクションから正規化されたVector2を返します。斜め移動が正しく処理され、ベクトルの長さは常に1.0または0.0なので、斜め移動が縦横移動より速くなりません。 -
No gravity is applied since this is a top-down view. The character stops immediately when no input is given because we set
velocitydirectly (no inertia). トップダウンビューなので重力は適用されません。velocityを直接設定するため(慣性なし)、入力がないときキャラクターは即座に停止します。
Adding Acceleration and Friction
加速と摩擦の追加
For a smoother feel with acceleration and deceleration:
加速と減速でより滑らかな操作感にするには:
extends CharacterBody2D
const SPEED = 200.0
const ACCELERATION = 1200.0
const FRICTION = 1000.0
func _physics_process(delta: float) -> void:
var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if input_direction != Vector2.ZERO:
velocity = velocity.move_toward(input_direction * SPEED, ACCELERATION * delta)
else:
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
move_and_slide()
5. 3D Third-Person Controller 5. 3Dサードパーソンコントローラー
The 3D version follows the same pattern. The main difference is working with Vector3 and using transform.basis to convert 2D input into 3D world-space movement.
3D版も同じパターンに従います。主な違いはVector3を使用し、transform.basisで2D入力を3Dワールド空間の移動に変換する点です。
extends CharacterBody3D
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
func _physics_process(delta: float) -> void:
# Apply gravity
if not is_on_floor():
velocity += get_gravity() * delta
# Jump
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get input and convert to 3D direction
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
Key Differences from 2D
2Dとの主な違い
-
Units: In 3D, 1 unit = 1 meter (convention). So
SPEED = 5.0means 5 meters per second — much smaller numbers than 2D pixel values. 単位: 3Dでは1単位 = 1メートル(慣例)。SPEED = 5.0は秒速5メートルを意味し、2Dのピクセル値よりずっと小さい数値です。 -
Jump velocity is positive: In 3D, Y-axis points upward (unlike 2D), so
JUMP_VELOCITY = 4.5is positive. ジャンプ速度は正: 3DではY軸が上向き(2Dとは逆)なので、JUMP_VELOCITY = 4.5は正の値です。 -
Direction transform:
transform.basis * Vector3(input_dir.x, 0, input_dir.y)converts 2D input into a 3D direction relative to the character's facing. The input's Y maps to the Z axis (forward/backward in 3D). 方向変換:transform.basis * Vector3(input_dir.x, 0, input_dir.y)は2D入力をキャラクターの向きに対する3D方向に変換します。入力のYがZ軸(3Dの前後)にマッピングされます。 -
Only X and Z are controlled: We set
velocity.xandvelocity.zseparately, leavingvelocity.yfor gravity and jumping. XとZのみ制御:velocity.xとvelocity.zを個別に設定し、velocity.yは重力とジャンプ用に残します。
The get_gravity() method was added in Godot 4.4. For older versions, use Vector2(0, ProjectSettings.get_setting("physics/2d/default_gravity")) for 2D, or Vector3(0, -ProjectSettings.get_setting("physics/3d/default_gravity"), 0) for 3D.
get_gravity()メソッドはGodot 4.4で追加されました。古いバージョンでは、2Dの場合はVector2(0, ProjectSettings.get_setting("physics/2d/default_gravity"))、3Dの場合はVector3(0, -ProjectSettings.get_setting("physics/3d/default_gravity"), 0)を使用してください。
6. Key Properties Reference 6. 主要プロパティリファレンス
Both CharacterBody2D and CharacterBody3D share these important properties. Adjust them in the Inspector or via code.
CharacterBody2DとCharacterBody3Dの両方が共有する重要なプロパティです。インスペクタまたはコードで調整できます。
| Propertyプロパティ | Type型 | Defaultデフォルト | Description説明 |
|---|---|---|---|
velocity |
Vector2 / Vector3 | Vector2.ZERO |
The character's velocity. Set this before calling move_and_slide(). Updated after the call with the resulting velocity.
キャラクターの速度。move_and_slide()を呼ぶ前に設定。呼び出し後は結果の速度で更新されます。
|
floor_snap_length |
float | 1.0 |
Replaces move_and_slide_with_snap(). Distance to snap the character to the floor. Set to 0 to disable. Useful for slopes and stairs.
move_and_slide_with_snap()の代替。キャラクターを床にスナップする距離。0で無効化。坂道や階段に便利。
|
up_direction |
Vector2 / Vector3 | Vector2.UP |
Defines which direction is "up". This determines what counts as floor, wall, or ceiling. Default is (0, -1) in 2D, (0, 1, 0) in 3D.
「上」の方向を定義。これにより床・壁・天井の判定が決まります。デフォルトは2Dで(0, -1)、3Dで(0, 1, 0)。
|
floor_stop_on_slope |
bool | true |
When true, the character won't slide down slopes when standing still. Essential for platformers. trueの場合、静止時にキャラクターが坂道で滑りません。プラットフォーマーに必須。 |
floor_max_angle |
float | 0.785 (45°) |
Maximum walkable slope angle in radians. Surfaces steeper than this are treated as walls. Use deg_to_rad(60) to set 60 degrees.
歩行可能な最大勾配角度(ラジアン)。これより急な面は壁として扱われます。60度に設定するにはdeg_to_rad(60)を使用。
|
max_slides |
int | 6 |
Maximum number of collision iterations per move_and_slide() call. Higher values are more accurate but slower.
move_and_slide()呼び出しごとの最大衝突反復回数。値が大きいほど正確だが遅くなります。
|
wall_min_slide_angle |
float | 0.262 (15°) |
Minimum angle for wall sliding. Prevents the character from getting stuck on nearly-parallel walls. 壁スライドの最小角度。ほぼ平行な壁にキャラクターが引っかかるのを防ぎます。 |
platform_on_leave |
PlatformOnLeave | ADD_VELOCITY |
Behavior when leaving a moving platform. ADD_VELOCITY preserves momentum, ADD_UPWARD_VELOCITY only adds upward component, DO_NOTHING ignores platform velocity.
移動プラットフォームを離れた時の挙動。ADD_VELOCITYで運動量を保存、ADD_UPWARD_VELOCITYで上方成分のみ追加、DO_NOTHINGでプラットフォームの速度を無視。
|
slide_on_ceiling |
bool | true |
When true, allows sliding on ceilings. When false, stops horizontal velocity on ceiling hit. trueの場合、天井でのスライドを許可。falseの場合、天井に当たると水平速度が停止。 |
7. Collision Detection After move_and_slide() 7. move_and_slide()後の衝突検出
After calling move_and_slide(), you can inspect the collisions that occurred. This is useful for reacting to specific collider types, playing sound effects on landing, or implementing wall-jump mechanics.
move_and_slide()を呼んだ後、発生した衝突を検査できます。特定のコライダータイプへの反応、着地時のサウンドエフェクト再生、壁ジャンプの実装などに便利です。
func _physics_process(delta: float) -> void:
# ... set velocity here ...
move_and_slide()
# Check all collisions from this frame
for i in get_slide_collision_count():
var collision := get_slide_collision(i)
var collider := collision.get_collider()
print("Collided with: ", collider.name)
print("Normal: ", collision.get_normal())
print("Position: ", collision.get_position())
# Practical example: bounce off enemies
for i in get_slide_collision_count():
var collision := get_slide_collision(i)
if collision.get_collider().is_in_group("enemies"):
velocity = collision.get_normal() * 300
break
Useful KinematicCollision Methods
便利なKinematicCollisionメソッド
get_collider()— The object that was hit.ヒットしたオブジェクト。get_normal()— The collision surface normal. Points away from the surface.衝突面の法線。面から離れる方向。get_position()— The point in world space where the collision occurred.衝突が発生したワールド空間上の点。get_travel()— How far the body traveled before colliding.衝突前にボディが移動した距離。get_remainder()— The remaining motion that was not applied.適用されなかった残りのモーション。get_collider_velocity()— Velocity of the collider (useful for moving platforms).コライダーの速度(移動プラットフォームに便利)。
8. Migration Cheat Sheet 8. 移行チートシート
Quick reference for converting Godot 3 code to Godot 4:
Godot 3からGodot 4への変換クイックリファレンス:
| Godot 3 | Godot 4 |
|---|---|
KinematicBody2D |
CharacterBody2D |
KinematicBody3D |
CharacterBody3D |
velocity = move_and_slide(velocity, Vector2.UP) |
velocity = ... |
move_and_slide_with_snap(vel, snap, up) |
floor_snap_length = 4.0 |
var vel = move_and_slide(...)returns velocityvelocityを返す |
move_and_slide()velocity property is updated in-placevelocityプロパティが直接更新される |
var gravity = ProjectSettings.get("physics/2d/default_gravity") |
get_gravity() (4.4+) |
move_and_slide(..., up_direction, ...) |
up_direction = Vector2.UP (set as property)(プロパティとして設定) |
move_and_slide(..., stop_on_slope, ...) |
floor_stop_on_slope = true (set as property)(プロパティとして設定) |
When opening a Godot 3 project in Godot 4, the engine offers to convert your project. It renames nodes and attempts to update scripts, but it does not always get move_and_slide() calls right. You'll likely need to manually fix your movement code.
Godot 4でGodot 3プロジェクトを開くと、エンジンがプロジェクトの変換を提案します。ノードの名前変更やスクリプトの更新を試みますが、move_and_slide()の呼び出しは必ずしも正しく変換されません。移動コードの手動修正が必要になることが多いです。
9. Common Mistakes 9. よくある間違い
Mistake 1: Passing arguments to move_and_slide()
間違い1: move_and_slide()に引数を渡す
# ERROR: move_and_slide() takes no arguments in Godot 4
velocity = move_and_slide(velocity, Vector2.UP)
# Set velocity, then call move_and_slide() with no arguments
velocity.x = direction * SPEED
move_and_slide()
Mistake 2: Forgetting to set velocity before move_and_slide()
間違い2: move_and_slide()の前にvelocityを設定し忘れる
func _physics_process(delta: float) -> void:
move_and_slide() # velocity is Vector2.ZERO — nothing happens
Mistake 3: Using _process() instead of _physics_process()
間違い3: _physics_process()の代わりに_process()を使用
move_and_slide() must be called in _physics_process(), which runs at a fixed rate (default 60 Hz). Using _process() ties physics to the rendering frame rate, causing inconsistent behavior.
move_and_slide()は固定レート(デフォルト60Hz)で実行される_physics_process()内で呼ぶ必要があります。_process()を使うと物理がレンダリングフレームレートに連動し、挙動が不安定になります。
Mistake 4: Not setting up CollisionShape
間違い4: CollisionShapeを設定していない
A CharacterBody2D/CharacterBody3D without a CollisionShape child will move through everything. Godot shows a warning icon in the editor if the collision shape is missing.
CollisionShape子ノードのないCharacterBody2D/CharacterBody3Dはすべてを通り抜けます。衝突形状がない場合、エディタに警告アイコンが表示されます。
Mistake 5: Overwriting velocity.y with gravity every frame
間違い5: 毎フレームvelocity.yを重力で上書きする
# This overwrites any jump velocity!
velocity.y = gravity * delta # should be +=, not =
# Gravity accumulates over time
velocity += get_gravity() * delta
Mistake 6: Applying gravity when on the floor
間違い6: 床の上にいるとき重力を適用する
Always wrap gravity in if not is_on_floor(). Without this check, gravity keeps accumulating while on the floor. When the character walks off a ledge, it will plummet at an extreme speed instead of falling naturally.
重力は必ずif not is_on_floor()で囲んでください。このチェックがないと、床の上でも重力が蓄積し続けます。キャラクターが崖から歩いて落ちるとき、自然に落下する代わりに極端な速度で急降下します。