Game feel (juice)
The difference between a mechanic that works and one that feels good is feedback: the layered, slightly-exaggerated response an action provokes. This skill covers the engine- neutral techniques — screen shake, hit-stop, easing, squash & stretch, knockback, and stacked feedback — and tells you how to apply them without burying the underlying simulation. It adds polish on top of an existing mechanic; it does not implement the mechanic.
When to use
- Use when an action (hit, jump, dash, pickup, death, button press) is mechanically correct but feels weak, weightless, or unsatisfying, and you want it to feel responsive and punchy.
- Use to add screen shake, hit-stop/freeze frames, eased motion, squash & stretch, knockback, flashes, or to layer multiple feedback channels onto one event.
- Use to decide how much juice is enough and where it crosses into noise.
When not to use: for the raw controller math (jump height, coyote time) use the
platformer genre and the engine movement skill. For camera follow/deadzone/orbit framing
use camera-systems (this skill only triggers the shake). For mixing, ducking, and adaptive
music use audio-design. For shader-based dissolves/flashes use shader-programming and the
engine shader skill. For the concrete tween/particle node APIs, use the engine animation skill
(godot-animation, unity-animation).
Core principle: feedback is layered and exaggerated
One satisfying hit is usually 5–8 tiny responses firing together within ~100 ms: a sound, a particle burst, a brief hit-stop, a flash, a knockback, a small screen shake, and a number popping up. Each is cheap; stacked, they read as "impact". Two rules keep it from becoming a mess: (1) exaggerate briefly and return to rest (juice is transient, not a new resting state); (2) scale juice to event importance — a footstep is not a boss death.
Core workflow
- Confirm the event hooks exist. Juice attaches to discrete events:
on_hit,on_land,on_pickup,on_death,on_fire. If the mechanic doesn't emit these, add them first. - Pick feedback channels per event from the menu (sound, particles, shake, hit-stop, flash, knockback, tween, number pop). Start with 2–3; add until it reads, then stop.
- Make motion eased, not linear. Route scale/position/UI changes through a tween with an ease (overshoot for "pop", ease-out for "settle"). Linear motion feels robotic.
- Reserve hit-stop and shake for impact. They are the strongest, most abusable tools — short durations, scaled to importance, and never on routine actions.
- Keep feedback off the critical simulation. Shake moves the camera/visual, not the body; hit-stop uses time scale or a real-time pause, not a gameplay-logic stall.
- Tune by importance tiers. Define small/medium/large feedback presets and assign events to a tier, so the whole game's juice stays consistent and proportional.
- Verify by playing and watching. Trigger the event repeatedly; confirm the feedback fires, returns to rest, and is not nauseating or input-blocking. Report what you observed (does shake decay? does input still register during hit-stop?).
Patterns
1. Screen shake by decaying "trauma" (smooth, not a random jitter)
2. Hit-stop / freeze frame (sell impact by briefly stopping time)
3. Squash & stretch + overshoot via an eased tween (the "pop")
4. A feedback bundle scaled by importance (keep juice proportional)
Pitfalls
- Shaking the player/body instead of the camera offset desyncs collision and aim. Shake the camera (or a visual pivot), never the simulated transform.
- Random offset every frame buzzes like static. Drive shake from sampled noise/sin and a decaying trauma value so it's smooth and self-ending.
- Hit-stop with
WaitForSeconds/ a scaled timer never resumes (at time scale 0 the timer never advances). Use a real-time wait (WaitForSecondsRealtime, or Godot'signore_time_scaletimer). - Hit-stop on every frame of a held attack locks the game. Trigger it once per impact.
- Linear tweens everywhere feel robotic. Ease almost everything; reserve overshoot (BACK/ELASTIC) for "pop" and ease-out for "settle".
- Permanent exaggeration (scale never returns, shake never decays) becomes the new normal and stops reading as feedback. Juice must return to rest.
- Over-juicing routine actions (full shake + hit-stop on every footstep) causes nausea and hides real impacts. Scale to importance; add a "reduce screen shake"/"reduce flashing" accessibility option.
- Feedback that blocks input (long freeze, un-cancelable animation) hurts responsiveness. Keep juice short and let input buffer through it.
References
- For the trauma-shake math, easing-curve cheat sheet (which ease for pop vs settle), knockback
- flash + number-pop recipes, importance-tier presets, and per-engine tween/particle bindings,
read
references/feedback-recipes.md.
- flash + number-pop recipes, importance-tier presets, and per-engine tween/particle bindings,
read
Related skills
camera-systems— owns camera follow/deadzone/orbit; this skill only feeds it shake trauma.godot-animation,unity-animation— concrete tween/AnimationPlayer/particle APIs juice rides on.audio-design— the sound layer of every feedback bundle; ducking and SFX variation.physics-tuning— knockback forces and the timestep juice must not destabilize.platformer,fps-shooter,roguelike— genres whose moment-to-moment feel this elevates.
