動摩擦
この記事は Godot 3から Godot 4 へ内容の書き換え中です。 Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリのIssuesまでご報告ください。
課題
運動キャラクターに摩擦と加速度を加え、より自然な動きを実現したい。
解決策
多くのゲームにおいて、必ずしも完全な物理シミュレーションを求めているわけではありません。重要なのはアクション性、反応の良さ、そしてアーケードならではの爽快感です。だからこそ、RigidBodyではなくKinematicBodyを選択するのです - これによって物体の動きを直接制御できるようになります。ただし、ある程度の物理的な挙動は必要です。これはつまり、オブジェクトが突然方向を変えたり停止したりしないようにするためです。
以下に、シンプルな運動力学に基づくプラットフォーマーキャラクター用のコードを示します。
extends CharacterBody2D
var speed = 1200
var jump_speed = -1800
var gravity = 4000
var velocity = Vector2.ZERO
func get_input():
velocity.x = 0
if Input.is_action_pressed("ui_right"):
velocity.x += speed
if Input.is_action_pressed("ui_left"):
velocity.x -= speed
func _physics_process(delta):
get_input()
velocity.y += gravity * delta
move_and_slide()
if Input.is_action_just_pressed("ui_select"):
if is_on_floor():
velocity.y = jump_speed
このコードを実行すると、キャラクターのx方向速度が瞬時に変化してしまうことに気づくでしょう。これを修正するために、lerp()関数を使用して速度を徐々に増減させるようにします。
lerpの使用例
lerp(start_value, end_value, amount)
lerp()(線形補間)は、2つの数値間で「ブレンドされた」値を求める関数です。詳細は補間処理を参照してください。
以下のコードでは、friction(摩擦係数)はキャラクターが停止する速度を、acceleration(加速力)は最大加速するまでの速度を決定する要素です。どちらも値が0.0から1.0の範囲内で設定されます。
get_input()のコードを以下に置き換えます。
var friction = 0.1
var acceleration = 0.5
func get_input():
var input_dir = 0
if Input.is_action_pressed("ui_right"):
input_dir += 1
if Input.is_action_pressed("ui_left"):
input_dir -= 1
if dir != 0:
# accelerate when there's input
velocity.x = lerp(velocity.x, dir * speed, acceleration)
else:
# slow down when there's no input
velocity.x = lerp(velocity.x, 0, friction)
解説
friction(摩擦係数)とacceleration(加速力)をブレンド量として使用します。speedには、現在速度から最大速度までの適切な値を求めます。減速時には、現在速度を徐々に0へ減衰させます。
値に 1.0 を使用すると、当初の「瞬間的な」移動状態が復活します。