Docs: camera feel session log (look-ahead de-jar + zoom)
Session log for the PrototypeCameraRig walk-shift fix: root cause, the separate-view-position fix, genre research (Diablo/PoE/Hades/Cinemachine), and the live-tunable knobs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
||||||
Reference in New Issue
Block a user