Godot4 動く地形でジャンプしたときに慣性をつけるスクリプト例

無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、簡単に落下・ジャンプ・横移動などを実現できる CharacterBody2D クラスのスケルトンコード(自動的に作られるコード)に、処理を追加して、動く地形の上でジャンプをしたときに、慣性をつけたジャンプを実装します。
get_platform_velocity 関数を使用するタイミングについても紹介しました。

Godot4 動く地形でジャンプする際に地形の加速度を付加して慣性のあるジャンプを実装

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※紹介するスクリプトは自己責任でお使いください。

前回の記事

簡単に左右に移動したりジャンプする挙動を実装できる CharacterBody2D クラスのスケルトンコード処理の意味について紹介しました。

動く地形に乗った時のジャンプの挙動

ゲームにもよりますが、動く地形に乗っているときにジャンプをすれば、真上に飛んでも、慣性によって動く地形の移動方向に影響を受ける方が自然かもしれません。

Godot4 動く地形でジャンプしても慣性がなく不自然です。

動く地形の加速度を足した慣性のあるジャンプの実装

CharacterBody2D の get_platform_velocity メンバ関数を用いると、着地している地形の加速度を得られます。
これを用いて、ジャンプする際に、地形の移動方向への慣性をつけます。
# 着地しているかを判定できる is_on_floor 関数とあわせて、開発者に配慮した便利関数がたくさんあって GodotEngine はすばらしい!

Vector2 get_platform_velocity() const 

Returns the linear velocity of the platform at the last collision point. Only valid after calling move_and_slide.

CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント

前回紹介した CharacterBody2D ノードに新規作成したスクリプト(落下・ジャンプ・着地・横移動ができるデフォルトのスケルトンコード)に、 get_platform_velocity メンバ関数による着地している地形の加速度ジャンプ時の慣性にする処理を追加します。

スケルトンコードの処理の説明については前回の記事を参照してください。

動く地形で慣性をつけたジャンプをするスクリプトの紹介

以下が、動く地形の加速度を加えてジャンプを行うスクリプトです。
順番にスケルトンコードへの追加点・変更点を紹介します。
また、スクリプトにも説明のコメントを書いているので参考にしてください。
※慣性をつけたジャンプの処理は「Godot 4 Moving Platforms – YouTube」を参考にしました。

extends CharacterBody2D


const SPEED = 300.0 # 左右入力により設定する水平方向の加速度
const SPEED_REDUCE = 300.0	# 入力がない場合に、水平方向の加速度を減らすフレームあたりの上限値。とまりにくいキャラは SPEED より小さく設定します。
const JUMP_VELOCITY = -700. # ジャンプの加速度です。

# のっている地形の加速度。動いている地形でジャンプする場合に慣性をつけます。
var platform_velocity = Vector2(0, 0)

func _physics_process(delta):
	# 着地しているかどうかを取得(2回呼ぶのでキャッシュ変数に格納)
	var ret_is_on_floor:bool = is_on_floor()

	# Add the gravity.
	if not ret_is_on_floor:
		# 着地していない、空中にいる場合
		velocity += get_gravity() * delta # 重力により落下させます。

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		velocity.x += platform_velocity.x # ジャンプ時に、のっている地形の水平方向の加速度を加えることで慣性のあるジャンプを表現します。

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("ui_left", "ui_right") # 右入力: + の値, 左右入力なし: 0, 左入力: - の値
	if direction:
		# 左右どちらかに入力された場合
		velocity.x = direction * SPEED # 入力方向に加速
	else:
		# 左右の入力がない場合
		if ret_is_on_floor:
			# 左右移動せずに着地している場合
			
			# SPEED_REDUCE 単位で毎フレーム 0 に向けて減速します。
			# 氷の床などですべりやすくしたい場合、 SPEED_REDUCE をさらに減少させてください。
			velocity.x = move_toward(velocity.x, 0, SPEED_REDUCE) 

	move_and_slide() # 現在の velocity (加速度)で移動して、衝突などの相互作用も行います。
	platform_velocity = get_platform_velocity() # のっている地形に加速度を更新します。move_and_slide() 後に有効です。

定数の追加

SPEED 定数は、移動時の加速度を設定していました。
追加した SPEED_REDUCE 定数は、入力がない状態で移動中の状態から減速するための、減速の度合いを表します。

const SPEED_REDUCE = 300.0	# 入力がない場合に、水平方向の加速度を減らすフレームあたりの上限値。とまりにくいキャラは SPEED より小さく設定します。

スケルトンコードの move_toward 関数で使われているように、SPEED と同じ値を設定します。

		velocity.x = move_toward(velocity.x, 0, SPEED)

変数の追加

キャラクターが乗っている地形の加速度を一時的に格納する変数を追加します。

# のっている地形の加速度。動いている地形でジャンプする場合に慣性をつけます。
var platform_velocity = Vector2(0, 0)

_physics_process イベント関数のローカルスコープに is_on_floor メンバ関数の結果を格納する変数を追加します。
これは、 is_on_floor メンバ関数を2回呼ぶようにしたので、関数を呼び出す回数を1回にするためです。
着地していれば true, 着地していない(空中にいる)場合は false が格納されます。

	# 着地しているかどうかを取得(2回呼ぶのでキャッシュ変数に格納)
	var ret_is_on_floor:bool = is_on_floor()

スケルトンコードで落下処理を行うかどうかの判定で用いていて is_on_floor メンバ関数は事前に呼ぶことにしたので、その結果をいれた変数をかわりに if 文の条件に設定します。

	if not ret_is_on_floor:

ジャンプ入力がされた際の処理に 23 行目を追加します。
これにより、ジャンプする際に動く地形の加速度の X 方向の値が、キャラクターの加速度に加算されて、慣性のついたジャンプを実現します。

platform_velocity 変数へ動く地形の加速度格納する処理は、仕様上 move_and_slide メンバ関数を呼び出した後に行うので、1回前(デフォルトでは約 1/60 秒前)の _physics_process イベント関数で得た加速度が格納されています。
※初回の場合は (0, 0) の初期値が使用されます。

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		velocity.x += platform_velocity.x # ジャンプ時に、のっている地形の水平方向の加速度を加えることで慣性のあるジャンプを表現します。

ジャンプ時は減速させない条件分岐

前の章で、ジャンプ時に動く地形の加速度を加えて慣性のあるジャンプを実装しました。

次は、その処理を追加したことによる調整です。
ジャンプ時は、左右移動の入力をしなくても、ジャンプ時に加えた動く地形の加速度を自然に減少させるため、

左右移動の入力がない場合に減速するのではなく

左右移動の入力がない&着地している場合に減速するようにします。

そのため else のあとに if ret_is_on_floor: という「着地していれば」という条件を追加して、そのあとに減速の処理を移動しました。
これにより、空中にいる場合は move_toward 関数は呼び出されず、自然な減速だけが行われます。

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("ui_left", "ui_right") # 右入力: + の値, 左右入力なし: 0, 左入力: - の値
	if direction:
		# 左右どちらかに入力された場合
		velocity.x = direction * SPEED # 入力方向に加速
	else:
		# 左右の入力がない場合
		if ret_is_on_floor:
			# 左右移動せずに着地している場合
			
			# SPEED_REDUCE 単位で毎フレーム 0 に向けて減速します。
			# 氷の床などですべりやすくしたい場合、 SPEED_REDUCE をさらに減少させてください。
			velocity.x = move_toward(velocity.x, 0, SPEED_REDUCE) 

動く地形の加速度の更新

変数 platform_velocity に、のっている地形の加速度を取得して格納します。

	move_and_slide() # 現在の velocity (加速度)で移動して、衝突などの相互作用も行います。
	platform_velocity = get_platform_velocity() # のっている地形に加速度を更新します。move_and_slide() 後に有効です。

get_platform_velocity メンバ関数は move_and_slide をしたあとに有効な値を得られるので、そのようにします。

Vector2 get_platform_velocity() const 

Returns the linear velocity of the platform at the last collision point. Only valid after calling move_and_slide.

最後の衝突点でのプラットフォームの線速度を返します。 move_and_slide を呼び出した後にのみ有効です。

CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント

動く地形で慣性のついたジャンプのテスト

シーンドックでステージのシーンを開いてから F6 キー実行します。
動く地形(紫色)にのって、真上にジャンプすると、動く地形の移動方向への慣性がついたジャンプができました。

Godot4 動く地形でジャンプする際に地形の加速度を付加して慣性のあるジャンプを実装
Godot4 CharacterBody2D 地形の加速度を付加して慣性のついたジャンプ1

仕様通りですが、左右に動く地形が、向きを変える直前にジャンプした場合は、動く地形の移動方向が変わった後の加速度は無関係のため、動く地形の下には着地できません。

Godot4 CharacterBody2D 地形の加速度を付加して慣性のついたジャンプ2

まとめ

今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、簡単に落下・ジャンプ・横移動などを実現できる CharacterBody2D クラスのスケルトンコード(自動的に作られるコード)に、処理を追加して、動く地形の上でジャンプをしたときに、慣性をつけたジャンプを実装しました。
get_platform_velocity 関数を使用するタイミングについても紹介しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました