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.
Variants
Section titled “Variants”| Variant | Use when |
|---|---|
platformer-2d | Side-scroller with gravity, jumps, ground / air handling. The Platformer bundle ships this. |
topdown-2d | Top-down 8-directional movement, no gravity. The Top-down RPG bundle ships this. |
third-person-3d | Third-person camera with relative movement and a chase cam. |
first-person-3d | First-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.
Tuning constants
Section titled “Tuning constants”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.
| Key | Default | What it does | Reference |
|---|---|---|---|
coyoteTimeMs | 100 | Grace after walking off a ledge where a jump still counts | Celeste, SMW |
jumpBufferMs | 100 | Window before landing where a queued press fires | SMB1, Celeste |
accelTimeSec | 0.15 | Time to reach max speed from 0 | Between Hollow Knight and Celeste, snappy but not twitchy |
decelTimeSec | 0.10 | Time to stop from max speed | Snappier than accel; release feels responsive without ice |
maxFallSpeed | 18 | Terminal fall velocity | Clamp prevents tunneling through ground colliders |
airControl | 0.7 | 0..1 multiplier on accel while airborne | 0.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.
Mechanics
Section titled “Mechanics”Toggles for optional moves. They’re off by default; flipping them on regenerates the controller to include the relevant logic.
| Mechanic | What it does |
|---|---|
| Double jump | Extra mid-air jump (only available once between landings). |
| Wall slide | Slow fall against walls. Holding direction into wall slows descent. |
| Wall jump | Push off walls. Requires wall slide. |
| Dash | Short directional burst. Independent cooldown. |
| Sprint | Modifier key held boosts move speed (optional; surfaces only on platformer variant). |
Why these defaults
Section titled “Why these defaults”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.
Editing the config by hand
Section titled “Editing the config by hand”[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 = trueThe 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.