diff --git a/Docs/Vault/07_Sessions/2026/2026-06-11_Camera_Feel_LookAhead_Zoom.md b/Docs/Vault/07_Sessions/2026/2026-06-11_Camera_Feel_LookAhead_Zoom.md new file mode 100644 index 000000000..47471f96d --- /dev/null +++ b/Docs/Vault/07_Sessions/2026/2026-06-11_Camera_Feel_LookAhead_Zoom.md @@ -0,0 +1,52 @@ +--- +date: 2026-06-11 +type: session +tags: +- session +- camera +- presentation +- juice +- tuning +permalink: gamevault/07-sessions/2026/2026-06-11-camera-feel-lookahead-zoom +--- + +# Camera feel — de-jar the walk look-ahead + pull the default zoom in + +> Operator complaint: "the camera shift when walking around is jarring — get rid of it or make it a LOT more subtle; also bring the default zoom a little closer." Small-track [[dots-dev]] feel pass on the prototype follow cam. Compile clean, values verified on disk; the **feel** sign-off is the operator's Play-mode pass (smoothing-over-time can't be screenshotted). + +## Root cause +`PrototypeCameraRig.cs` (client MonoBehaviour on the Main Camera, `LateUpdate`) added the movement look-ahead **raw** onto the framed point — `target += normalize(TargetMoveDir) * AimLeadDistance` (2.5 u) — with smoothing applied **only to the final camera position** (`FollowSharpness = 8`). Because `TargetMoveDir` is the *instantaneous input* Move vector, the lead target is effectively binary: full 2.5 u while a key is held, 0 when released. Start/stop pans the view; **reversing direction swings the target ~5 u**. The position-follow filter chases that jumping target → the jarring "shift when walking." + +## Fix (the genre-standard "separate view position" technique) +Web precedent (dual-stick design write-ups, Cinemachine's Lookahead Time/Smoothing, damped-spring articles) all converge: don't add the raw lead — give the look-ahead its **own target and a separately-smoothed offset**. Implemented exactly that: + +- **New `Vector3 _leadOffset` field**, eased toward `desiredLead` each frame at a new **`[Min(0)] float LeadSharpness = 3f`** knob (`1 - exp(-LeadSharpness*dt)`, ≈0.33 s ease — deliberately gentler than `FollowSharpness = 8`). The desired lead still snaps with input; `_leadOffset` glides, so start / stop / reverse no longer bump. Matches the file's existing exponential-smoothing idiom (shake, FOV-kick, follow all use `1 - exp(-k*dt)`). +- **`AimLeadDistance` default 2.5 → 1.0** (subtle, on-genre; Hades-style gentle lead rather than Diablo/PoE's zero). `0` is the one-number kill switch → fully centred. +- **`Distance` default 16 → 13** (~19 % closer along the view ray; operator picked "a touch closer" over 11/14.5). +- Updated tooltips to document the 0 = fully-centred behaviour and the new knob. + +Code defaults **and** the serialized `Game.unity` Main Camera values were both updated (serialized overrides win), then the scene was saved. + +## Genre research (operator asked) +Top-down/ARPG/twin-stick camera conventions: +- **Diablo / PoE / PoE2** — effectively centred, **zero** look-ahead. Maximally stable. +- **Hades / twin-stick shooters** — gentle, **heavily-smoothed** lead toward movement/aim with a magnitude cap. +- The classic "bump" fix is a lead with its **own target + view position** (separate speed) — i.e. don't track the raw input. Cinemachine exposes this as Lookahead Time + Lookahead Smoothing. +- **Critically-damped spring / `SmoothDamp`** stays smooth even when the target jumps (velocity-aware) — noted as the next step if the exponential ease ever feels insufficient on reversals; not needed for "subtle." + +## What we did NOT do (deliberate, minimal change) +- No deadzone / soft-zone camera (bigger rework). +- Did not swap the position follow to `SmoothDamp` — the existing exponential follow is fine once the lead is independently eased. +- Left `SampleScene`/`DevSandbox` camera values untouched (dev/reference scenes; the live gameplay scene is `Game.unity`). + +## Validation +- **Compile:** forced `refresh_unity scope=scripts` (editor was unfocused), domain reload completed, **0 errors / 0 warnings**. +- **Values on disk:** `Game.unity` Main Camera `PrototypeCameraRig` → `Distance: 13`, `AimLeadDistance: 1`, `LeadSharpness: 3` (verified in YAML + via the component resource). +- **Feel:** OPEN — operator Play-mode pass. Every value stays a live-tunable Inspector knob: dial `AimLeadDistance` 1→0 to fully centre, `Distance` 13→11 for closer, `LeadSharpness` lower for an even slower glide. + +## Files +- `Assets/_Project/Scripts/Client/Presentation/PrototypeCameraRig.cs` — independent lead smoothing + `LeadSharpness` knob; default `AimLeadDistance` 2.5→1, `Distance` 16→13. +- `Assets/Scenes/Game.unity` — Main Camera serialized `Distance`/`AimLeadDistance`/`LeadSharpness`. + +## Next-session intent +Operator feel-test the walk pan + zoom; if the lead still reads at all, drop `AimLeadDistance` to 0 (centred) or lower `LeadSharpness`. If reversals ever bump under fast strafing, consider a `SmoothDamp` follow.