Godot入門:CharacterBody3Dの使い方と活用法

はじめに

3Dゲームでプレイヤーキャラクターを操作し、走ったりジャンプしたりさせるにはどうするのでしょう?その答えがCharacterBody3Dです。この記事では、3D空間での移動、重力、ジャンプの実装から、FPS・TPS視点での操作まで解説します。

この記事を読むことで、3D移動の基本、床判定、壁の衝突判定、そして実践的なゲームの操作が身につきます。




CharacterBody3Dの衝突判定の仕組み
CharacterBody3Dは床・壁・天井を検出でき、これらに応じた移動制御が実装できます。

CharacterBody3Dとは?

CharacterBody3Dは、3D空間でプレイヤーキャラクターを操作するための物理ボディノードです。2Dの CharacterBody2D に相当し、移動・重力・ジャンプの実装に特化しています。

CharacterBody3Dは「プレイヤーキャラクターの体」です。ユーザー入力を受け取り、床との接触を判定し、自然な動きを実現します。

継承ツリー:


CharacterBody3D
  ├── PhysicsBody3D
  │   ├── CollisionObject3D
  │   │   ├── Node3D
  │   │   │   └── Node
  │   │   └── ...
  │   └── ...
  └── ...

このノードを使うべき場面

CharacterBody3Dを使う場面:

  • プレイヤーキャラクターの移動(WASD、アナログスティック)
  • 重力の実装と床への着地判定
  • ジャンプ・落下の物理演算
  • FPS・TPS視点でのキャラクター操作
  • 敵キャラクターの移動(AI制御)

CharacterBody3Dを使わない場面:

  • 完全に静止したオブジェクト → StaticBody3D を使う
  • リアルな物理演算が必要(重い木箱が落ちるなど) → RigidBody3D を使う
  • 単なる衝突判定のみ → Area3D を使う

主なプロパティと機能

プロパティ 説明
velocity Vector3 現在の速度ベクトル。(x, y, z) で各軸の速度を表現
floor_max_angle float 床と見なす傾斜角度の上限。デフォルト45度
floor_snap_length float 床から若干浮いた状態を「着地」と見なす距離
floor_constant_speed bool 傾斜地でも一定の速度を保つ
up_direction Vector3 上方向。通常 Vector3.UP = (0, 1, 0)
motion_mode MotionMode GROUNDED(地面ベース)か FLOATING(浮遊ベース)
slide_on_ceiling bool 天井に触れたとき、滑るように移動

重要メソッド:


# 移動を実行(キャラクターのコリジョンに基づいて)
move_and_slide()

# 床に着地しているか判定
is_on_floor() -> bool

# 壁に接触しているか判定
is_on_wall() -> bool

# 天井に接触しているか判定
is_on_ceiling() -> bool

# 床との衝突情報を取得
get_floor_normal() -> Vector3

# 移動時の衝突回数を取得
get_slide_collision_count() -> int

コード例1:基本的な3D移動(WASD + 重力 + ジャンプ)


extends CharacterBody3D

@export var move_speed: float = 5.0
@export var jump_force: float = 10.0
@export var gravity: float = 20.0

func _process(delta: float) -> void:
    # 入力を取得
    var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

    # キャラクターの前方を基準に移動方向を計算
    var forward = -global_transform.basis.z  # 前方(Z軸負方向)
    var right = global_transform.basis.x     # 右方向

    var move_dir = (forward * input_dir.y + right * input_dir.x).normalized()

    # 水平方向の速度を設定
    velocity.x = move_dir.x * move_speed
    velocity.z = move_dir.z * move_speed

    # 重力を適用
    if not is_on_floor():
        velocity.y -= gravity * delta

    # ジャンプ
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = jump_force

    # 実際に移動
    move_and_slide()

コード例2:FPS視点での操作(マウスルック + キャラクター移動)


extends CharacterBody3D

@export var move_speed: float = 5.0
@export var jump_force: float = 10.0
@export var gravity: float = 20.0
@export var mouse_sensitivity: float = 0.005

@onready var camera = $Camera3D  # Camera3D を子ノードとして配置

var camera_x_rotation: float = 0.0

func _ready() -> void:
    # マウスをロック(ゲーム中は操作画面から出ない)
    Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _process(delta: float) -> void:
    # 入力を取得(カメラ方向を基準)
    var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    var forward = -global_transform.basis.z
    var right = global_transform.basis.x

    var move_dir = (forward * input_dir.y + right * input_dir.x).normalized()
    velocity.x = move_dir.x * move_speed
    velocity.z = move_dir.z * move_speed

    # 重力とジャンプ
    if not is_on_floor():
        velocity.y -= gravity * delta
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = jump_force

    move_and_slide()

func _input(event: InputEvent) -> void:
    # マウス移動でカメラを回転
    if event is InputEventMouseMotion:
        var mouse_motion = event as InputEventMouseMotion
        # Y軸周りに回転(左右の視点)
        rotate_y(-mouse_motion.relative.x * mouse_sensitivity)
        # X軸周りに回転(上下の視点)
        camera_x_rotation -= mouse_motion.relative.y * mouse_sensitivity
        camera_x_rotation = clamp(camera_x_rotation, -PI / 2, PI / 2)
        camera.rotation.x = camera_x_rotation

    # Escキーでマウスロック解除
    if event.is_action_pressed("ui_cancel"):
        Input.mouse_mode = Input.MOUSE_MODE_VISIBLE




CharacterBody3Dの移動ベクトル計算
キャラクターの前方(forward)と右方向(right)を基準に、入力に応じた移動ベクトルが計算されます。

もっと使いこなす:カスタマイズできるパラメータ

まずは基本を動かしてみてから、余裕が出たら試してみてください。

パラメータ 説明
velocity.y float Y軸(上下)の速度。重力とジャンプで制御
floor_block_on_wall bool 壁に沿って登りながら移動するのを防ぐ
platform_on_leave PlatformOnLeave 移動している床から離れたときの挙動
get_last_motion() Vector3 前フレームの実際の移動量を取得
get_collision_normal() Vector3 衝突面の法線ベクトルを取得
set_velocity() void 次フレームの速度を明示的に設定
velocity_to_direction() Vector3 速度から移動方向を正規化して取得

まとめ

CharacterBody3Dは、3Dゲームのプレイヤー操作の中心となるノードであり、velocity・move_and_slide()・床判定の3つの要素で、自然で快適な移動が実現できるノードです。

  • velocity で現在の速度を管理し、move_and_slide() で実際の移動を実行
  • is_on_floor()・is_on_wall()・is_on_ceiling() で環境判定を行い、リアルな動きを表現
  • FPS・TPS両方の視点に対応でき、キャラクターの向きを基準とした相対的な移動が可能

次回は、固定されたオブジェクト用の物理ボディ、StaticBody3Dについて解説します。




CharacterBody3Dのセットアップ例
CharacterBody3Dを親に、CollisionShape3D(衝突判定用)、MeshInstance3D(表示用)、Camera3D(視点用)を子ノードとしてセットアップします。

シリーズ:Godot 4 ノード解説

001〜040:各種ノード
  • 001 Node2D
  • 002 Sprite2D
  • 003 AnimatedSprite2D
  • 004 Label
  • 005 Button
  • 006 TextEdit
  • 007 Panel
  • 008 VBoxContainer / HBoxContainer
  • 009 TabContainer
  • 010 OptionButton
  • 011 CheckBox
  • 012 Slider
  • 013 LineEdit
  • 014 RichTextLabel
  • 015 Control
  • 016 NinePatchRect
  • 017 TextureRect
  • 018 ItemList
  • 019 Tree
  • 020 ColorPickerButton
  • 021 Timer
  • 022 AudioStreamPlayer / AudioStreamPlayer2D
  • 023 Marker2D
  • 024 Area2D
  • 025 CharacterBody2D
  • 026 RigidBody2D
  • 027 StaticBody2D
  • 028 TileMap
  • 029 Camera2D
  • 030 CollisionShape2D
  • 031 Polygon2D
  • 032 Line2D
  • 033 ParticleSystem2D / CPUParticles2D
  • 034 CanvasLayer
  • 035 Sprite3D
  • 036 SubViewport
  • 037 MultiplayerSpawner
  • 038 RemoteTransform2D
  • 039 NavigationAgent2D
  • 040 VisibleOnScreenNotifier2D
  • 051 Node3D
  • 052 MeshInstance3D
  • 053 Camera3D
  • 054 DirectionalLight3D
  • 055 CharacterBody3D

この記事はGodot 4.xをもとに執筆しています。

コメント