【Godot 4】Glider (滑空) コンポーネントの作り方

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

Unity 6 C#スクリプト 100本ノック

新品価格
¥1,230から
(2025/12/29 10:28時点)

Cocos Creator100本ノックTypeScriptで書く!

新品価格
¥1,250から
(2025/12/29 10:32時点)

横移動とジャンプまでは作れたけど、「滑空」みたいなちょっとしたアクションを入れようとすると、Player.gd がどんどん太っていきますよね。
Godot標準のチュートリアルに従うと、CharacterBody2D を継承した巨大プレイヤースクリプトを育てがちで、

  • ジャンプ、ダッシュ、二段ジャンプ、滑空…全部1ファイルに詰め込みがち
  • 敵や動く床にも「ちょっとだけ似たロジック」をコピペして地獄
  • プレイヤー固有の機能と、汎用的な「空中制御」がごちゃ混ぜ

こうなると、ちょっと挙動を変えたいだけでも怖くて触れなくなります。
そこで今回は、プレイヤー側にほぼ手を入れず「コンポーネントを1個アタッチするだけ」で滑空を実現する 「Glider」コンポーネント を作っていきましょう。

ポイントは:

  • プレイヤーは「ただの移動用スクリプト」にしておく
  • 滑空の判定・物理・入力は全部 Glider コンポーネントに閉じ込める
  • EnemyMovingPlatform にも、同じコンポーネントをポン付けできる

「継承より合成」で、Godotのシーンをスッキリさせていきましょう。

【Godot 4】フワッと落ちてスイスイ進む!「Glider」コンポーネント

コンポーネントの前提

このコンポーネントは、次のような「ホスト」ノードにアタッチして使う想定です:

  • CharacterBody2D または CharacterBody3D ではなく、今回は 2D専用 とします(簡潔のため)。
  • ホスト側(例: Player)は velocity: Vector2 を持っている(CharacterBody2D 標準フィールド)。
  • 横移動の入力はホスト側で行ってもOKですが、滑空中だけ横速度を上書き/補正 します。

GDScript フルコード


## Glider.gd
## 空中でボタン押しっぱなしの間、落下速度を制限しつつ横移動を強化するコンポーネント。
## CharacterBody2D にアタッチして使います。

class_name Glider
extends Node

## --- 設定パラメータ(インスペクタで調整可能) ---

@export_group("入力設定")
## 滑空に使うアクション名(InputMap で定義しておく)
@export var glide_action_name: String = "glide"

@export_group("滑空物理設定")
## 滑空中の最大落下速度(絶対値)。通常の重力よりもかなり小さめに。
@export var max_fall_speed: float = 80.0

## 滑空開始に必要な最低落下速度(これより上向きだと滑空しない)
## 例: 0 以下なら「完全に上昇が止まるまでは滑空しない」
@export var min_downward_speed_to_start: float = 0.0

## 滑空中に適用する「疑似重力」係数(0 に近いほど落ちない)
@export_range(0.0, 1.0, 0.05)
@export var glide_gravity_factor: float = 0.2

@export_group("横移動ブースト")
## 滑空中に上書きする横速度の絶対値(0以下なら「いじらない」)
@export var glide_horizontal_speed: float = 220.0

## 滑空中の横移動の加速の速さ(補間係数)
@export_range(0.0, 1.0, 0.05)
@export var glide_horizontal_lerp: float = 0.2

@export_group("その他")
## 地面に着地したら自動的に滑空を解除するか
@export var auto_cancel_on_floor: bool = true

## デバッグ用: 現在滑空中かどうかをインスペクタで確認できる
@export var debug_is_gliding: bool = false:
	set(value):
		debug_is_gliding = value

## --- 内部状態 ---
var _host_body: CharacterBody2D
var _is_gliding: bool = false


func _ready() -> void:
	## 親が CharacterBody2D であることを確認
	_host_body = get_parent() as CharacterBody2D
	if _host_body == null:
		push_warning("Glider コンポーネントは CharacterBody2D の子として使ってください。")
		set_process(false)
		return
	
	set_process(true)


func _process(delta: float) -> void:
	if _host_body == null:
		return
	
	## 地面に着地しているなら滑空終了
	if auto_cancel_on_floor and _host_body.is_on_floor():
		_set_gliding(false)
		return
	
	## 空中でのみ滑空を許可
	if _host_body.is_on_floor():
		_set_gliding(false)
		return
	
	## 入力状態
	var glide_pressed := Input.is_action_pressed(glide_action_name)
	
	if glide_pressed:
		## 滑空開始条件を満たしているか?
		if not _is_gliding:
			_try_start_glide()
		## すでに滑空中なら物理補正を行う
		if _is_gliding:
			_apply_glide_physics(delta)
	else:
		## ボタンを離したら終了
		_set_gliding(false)


func _try_start_glide() -> void:
	## まだ地面にいるなら滑空しない
	if _host_body.is_on_floor():
		return
	
	## 上向きに強く飛んでいる間は滑空開始しない(好みで調整)
	if _host_body.velocity.y < min_downward_speed_to_start:
		return
	
	_set_gliding(true)


func _apply_glide_physics(delta: float) -> void:
	var v := _host_body.velocity
	
	## --- 縦方向(落下)の制御 ---
	## 通常の重力がどこか別で適用されている前提で、
	## ここでは「最大落下速度を制限しつつ、疑似的に減速」させるイメージ。
	## 例: v.y が 300 とかになっても、max_fall_speed 付近まで抑える。
	
	# 落下速度を max_fall_speed までにクランプ
	if v.y > max_fall_speed:
		v.y = lerp(v.y, max_fall_speed, glide_gravity_factor)
	
	## --- 横方向のブースト ---
	if glide_horizontal_speed > 0.0:
		## 入力方向を取得(左右キーなど)
		var input_dir := Input.get_axis("move_left", "move_right")
		
		if input_dir != 0.0:
			var target_speed := glide_horizontal_speed * sign(input_dir)
			v.x = lerp(v.x, target_speed, glide_horizontal_lerp)
		## 入力が 0 のときは、ホスト側の処理に任せる(惰性で流れるなど)
	
	_host_body.velocity = v


func _set_gliding(value: bool) -> void:
	if _is_gliding == value:
		return
	_is_gliding = value
	debug_is_gliding = value
	
	## 将来的にアニメーションやSEをここでトリガーすると便利
	## 例:
	##   if value:
	##       _play_glide_start_effect()
	##   else:
	##       _play_glide_end_effect()


## --- 参考: 外部から状態を参照したいとき用のAPI ---

func is_gliding() -> bool:
	return _is_gliding

使い方の手順

手順①:InputMap にアクションを追加

  1. Godot のメニューから「Project > Project Settings」を開く。
  2. Input Map タブを開き、glide というアクションを追加。
  3. キーボードなら ShiftSpace、ゲームパッドなら Button B など好みのボタンを割り当て。
  4. すでに move_left / move_right がある前提で進めます。

手順②:プレイヤーシーンにコンポーネントをアタッチ

例えば、こんなプレイヤーシーンを用意します:

Player (CharacterBody2D)
 ├── Sprite2D
 ├── CollisionShape2D
 └── Glider (Node)  ← このノードに Glider.gd をアタッチ
  1. PlayerCharacterBody2D)の子に Node を追加し、名前を Glider に変更。
  2. その Glider ノードに、先ほどの Glider.gd をアタッチ。
  3. インスペクタでパラメータを調整:
    • glide_action_name = "glide"
    • max_fall_speed = 80(ふわっと落ちる感じ)
    • glide_horizontal_speed = 220(通常より少し速め)

手順③:Player 側は「普通の移動処理」のままでOK

プレイヤーのスクリプトは、いつも通り CharacterBody2D ベースで構いません。
滑空のロジックはすべて Glider コンポーネントが担当するので、Player 側には特別なコードは不要です。


## Player.gd(例)
extends CharacterBody2D

@export var move_speed: float = 160.0
@export var jump_speed: float = -320.0
@export var gravity: float = 900.0

func _physics_process(delta: float) -> void:
	var input_dir := Input.get_axis("move_left", "move_right")
	
	## 横移動(Glider はここに上書きで干渉してくるだけ)
	velocity.x = input_dir * move_speed
	
	## 重力
	if not is_on_floor():
		velocity.y += gravity * delta
	else:
		## ジャンプ
		if Input.is_action_just_pressed("jump"):
			velocity.y = jump_speed
	
	move_and_slide()

この状態でゲームを実行すると:

  • ジャンプしてから空中で glide アクションを押しっぱなしにすると、落下がかなりゆっくりになる
  • 同時に左右キーを押していると、滑空中だけ横移動がスイスイ速くなる
  • 地面に着地するか、ボタンを離すと滑空終了

手順④:敵や動く床にも「滑空」を付けてみる例

コンポーネントなので、プレイヤー以外にも同じものを簡単に付けられます。例えば、空中をフワフワ移動する敵:

FlyingEnemy (CharacterBody2D)
 ├── Sprite2D
 ├── CollisionShape2D
 └── Glider (Node)

FlyingEnemy.gdvelocity を適当に制御しつつ、Gliderglide_horizontal_speed を高めに設定すれば、
「一定高度からあまり落ちずに、横に高速で滑空する敵」などを作れます。
プレイヤー専用のロジックを一切コピペしていないのがポイントですね。


メリットと応用

この「Glider」コンポーネントを使うことで:

  • Player.gd が細くなる
    滑空ロジックが完全に別ファイルに分離され、プレイヤー本体は「移動」と「ジャンプ」だけに集中できます。
  • シーン構造がフラットで見やすい
    「Glider付きプレイヤー」「Glider付き敵」「Glider付き動く床」など、
    どのノードがどんな能力を持っているか、シーンツリーを見れば一目瞭然になります。
  • パラメータ違いの再利用がしやすい
    プレイヤー用、敵用、ギミック用などで max_fall_speedglide_horizontal_speed を変えるだけで、
    同じコンポーネントから多様な挙動を生み出せます。
  • テストやデバッグが楽
    debug_is_gliding を見れば状態が一発で分かるので、パラメータ調整もしやすいです。

「継承で PlayerGlide, PlayerDoubleJump と増やす」のではなく、
Glider コンポーネントをアタッチするだけ」という発想に切り替えると、
プロジェクトが大きくなっても管理がかなり楽になります。

改造案:滑空開始時に縦速度を即座にリセットする

「滑空ボタンを押した瞬間に、ストンと落ちていた速度を一気に殺したい」場合は、
_try_start_glide() を次のように改造してみると分かりやすいです:


func _try_start_glide() -> void:
	if _host_body.is_on_floor():
		return
	
	## 上方向に飛んでいる最中でも、即座に滑空したい場合はこの条件を外す
	# if _host_body.velocity.y < min_downward_speed_to_start:
	#     return
	
	_set_gliding(true)
	
	## 縦速度を即座に「滑空用の最大値」にリセット
	if _host_body.velocity.y > max_fall_speed:
		_host_body.velocity.y = max_fall_speed

これで、「落ち始めてからグライドすると、ガクッと減速してふわっと落ちる」気持ちいい挙動になります。
このように、コンポーネント単体をいじるだけでゲーム全体の滑空挙動を統一して変えられるのも、合成スタイルの強みですね。

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

Unity 6 C#スクリプト 100本ノック

新品価格
¥1,230から
(2025/12/29 10:28時点)

Cocos Creator100本ノックTypeScriptで書く!

新品価格
¥1,250から
(2025/12/29 10:32時点)

URLをコピーしました!