Godot 4 플랫포머 게임 feel 5요소 수치 기준

Godot 4 플랫포머에서 coyote time은 100ms(0.1초), jump buffer는 150ms(0.15초)가 권장 기본값입니다. 둘 다 _physics_process에서 float 타이머 변수를 delta만큼 감소시키는 방식으로 구현합니다 — coyote는 바닥을 떠난 직후 100ms 안의 점프 입력을 정상 점프로 처리하고, jump buffer는 착지 150ms 전에 누른 점프를 착지 순간 자동 발동시킵니다. 아래 표와 GDScript에 5요소 전체 수치를 정리합니다.

← hexisteme · 2026-06-13 · Godot 4 게임개발 실증 노트

플랫포머의 "손에 감기는 조작감"은 5가지 역학의 조합입니다. 하나라도 빠지면 사용자는 "어색하다"고 느끼지만 무엇이 문제인지는 짚지 못합니다. Mario(1985)~Celeste(2018)까지 업계 표준으로 정착된 수치를 Godot 4 GDScript로 정리합니다.

5요소 수치 기준표

#요소수치 기본값효과
1Coyote time100ms (0.1s)플랫폼 엣지에서 떨어진 직후 이 시간 안에 점프 → 정상 점프
2Jump buffer150ms (0.15s)착지 직전 점프 입력 → 착지 순간 자동 발동
3Variable jump heightrelease 시 vy × 0.45짧게 탭 = 낮은 점프, 홀드 = 높은 점프
4비대칭 중력하강 시 상승 중력 × 1.8묵직한 착지감, apex에서 hang time
5Screen shake on impact0.15s, intensity 6~12피격·착지 임팩트 시 카메라 흔들림

GDScript 구현 (CharacterBody2D 기반)

extends CharacterBody2D

const SPEED := 200.0
const JUMP_VELOCITY := -400.0
const GRAVITY_UP := 900.0     # 상승 중력
const GRAVITY_DOWN := 1620.0  # 하강 중력 (상승 × 1.8)

const COYOTE_TIME := 0.10     # 100ms
const JUMP_BUFFER := 0.15     # 150ms
const VARIABLE_JUMP_MULT := 0.45

var coyote_timer := 0.0
var jump_buffer_timer := 0.0
var was_on_floor := false

func _physics_process(delta: float) -> void:
    # 중력 (비대칭)
    var grav = GRAVITY_UP if velocity.y < 0 else GRAVITY_DOWN
    if not is_on_floor():
        velocity.y += grav * delta

    # Coyote time 갱신
    if is_on_floor():
        coyote_timer = COYOTE_TIME
    else:
        coyote_timer = maxf(0.0, coyote_timer - delta)

    # Jump buffer 갱신
    jump_buffer_timer = maxf(0.0, jump_buffer_timer - delta)
    if Input.is_action_just_pressed("jump"):
        jump_buffer_timer = JUMP_BUFFER

    # 점프 발동 (coyote + buffer 조합)
    if jump_buffer_timer > 0.0 and coyote_timer > 0.0:
        velocity.y = JUMP_VELOCITY
        jump_buffer_timer = 0.0
        coyote_timer = 0.0

    # Variable jump (키 놓으면 상승 속도 축약)
    if Input.is_action_just_released("jump") and velocity.y < 0:
        velocity.y *= VARIABLE_JUMP_MULT

    # 수평 이동
    var dir := Input.get_axis("move_left", "move_right")
    velocity.x = dir * SPEED

    move_and_slide()

Screen shake (Camera2D 기반)

extends Camera2D

var shake_intensity := 0.0
var shake_duration := 0.0

func shake(intensity: float, duration: float) -> void:
    shake_intensity = intensity
    shake_duration = duration

func _process(delta: float) -> void:
    if shake_duration > 0.0:
        shake_duration -= delta
        offset = Vector2(
            randf_range(-shake_intensity, shake_intensity),
            randf_range(-shake_intensity, shake_intensity)
        )
    else:
        offset = Vector2.ZERO

착지 시 $Camera.shake(8.0, 0.15), 피격 시 $Camera.shake(12.0, 0.15)로 호출합니다.

수치 조정 기준

hexisteme dev-notes — Godot 4 게임개발 실증 노트 · 목록 · CC-BY-NC-4.0