Skip to content

CharacterController

The CharacterController owns the player’s movement: variant (which game shape it is), the polish constants (coyote time, jump buffer, air control), and the mechanic toggles (double jump, wall slide, wall jump, dash).

Open it from Inspector → Systems → CharacterController → Open.

VariantUse when
platformer-2dSide-scroller with gravity, jumps, ground / air handling. The Platformer bundle ships this.
topdown-2dTop-down 8-directional movement, no gravity. The Top-down RPG bundle ships this.
third-person-3dThird-person camera with relative movement and a chase cam.
first-person-3dFirst-person pointer-locked camera. Future FPS bundle uses this.

Variant is sticky once chosen. Switching variants regenerates the controller source (the system gets re-scaffolded), so do it early in a project’s life before you’ve made lots of custom changes.

The tuning section ships defaults pinned from real games. The hints in the editor name the reference game so you know what feel each default targets.

KeyDefaultWhat it doesReference
coyoteTimeMs100Grace after walking off a ledge where a jump still countsCeleste, SMW
jumpBufferMs100Window before landing where a queued press firesSMB1, Celeste
accelTimeSec0.15Time to reach max speed from 0Between Hollow Knight and Celeste, snappy but not twitchy
decelTimeSec0.10Time to stop from max speedSnappier than accel; release feels responsive without ice
maxFallSpeed18Terminal fall velocityClamp prevents tunneling through ground colliders
airControl0.70..1 multiplier on accel while airborne0.7 = some control without floatiness

Edit any value in the editor and the dev server hot-reloads. If you’re tuning game feel, this is the single fastest loop in Forge: tweak, save, jump, observe.

Toggles for optional moves. They’re off by default; flipping them on regenerates the controller to include the relevant logic.

MechanicWhat it does
Double jumpExtra mid-air jump (only available once between landings).
Wall slideSlow fall against walls. Holding direction into wall slows descent.
Wall jumpPush off walls. Requires wall slide.
DashShort directional burst. Independent cooldown.
SprintModifier key held boosts move speed (optional; surfaces only on platformer variant).

The defaults aren’t arbitrary. They’re the same numbers the games most people would name as the platformer feel benchmarks use:

  • Celeste’s 100ms coyote time and 100ms jump buffer are basically industry standard now.
  • SMB1 popularized variable jump height (release-to-cut) which is wired by default.
  • Hollow Knight’s snappy accel/decel curves match the Forge defaults closely.

If you’re making a side-scroller and these defaults feel weird, you almost certainly want to start by tuning rather than by replacing. The defaults work for ~80% of platformers; the variations are deliberate stylistic choices, not bug fixes.

[systems.CharacterController.config]
variant = "platformer-2d"
[systems.CharacterController.config.tuning]
coyoteTimeMs = 100
jumpBufferMs = 100
accelTimeSec = 0.15
decelTimeSec = 0.10
maxFallSpeed = 18
airControl = 0.7
[systems.CharacterController.config.mechanics]
doubleJump = false
wallSlide = false
wallJump = false
dash = false
sprint = true

The actual movement code lives in the source file the spine instantiates. The platformer bundle’s src/systems/character-controller-platformer.ts is the canonical reference; the topdown variant lives at src/systems/character-controller-topdown.ts.