From f11fbc8c1c5182c4b08599a9f916b09958aed085 Mon Sep 17 00:00:00 2001 From: MelekTaus Moribundus Date: Sun, 28 Jun 2026 15:51:39 +0200 Subject: [PATCH] Keep the camera fixed when opening the pause menu SetPaused no longer Exits the active mode, so the First-Person/Free-Cam rig keeps its CinemachineCamera priority and the view stays frozen in place instead of blending back to the orbit camera. Pausing now only disables each rig's per-frame look input (dropping the controller's enabled flag) and parks the orbit rig in Disabled to free the cursor; resuming re-enters the same mode whose snap-to-current-view is a no-op, so there is no jump on close either. Co-Authored-By: Claude Opus 4.8 --- Assets/Scripts/GameModeManager.cs | 35 +++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Assets/Scripts/GameModeManager.cs b/Assets/Scripts/GameModeManager.cs index bdfe957..9cf7597 100644 --- a/Assets/Scripts/GameModeManager.cs +++ b/Assets/Scripts/GameModeManager.cs @@ -255,9 +255,15 @@ public class GameModeManager : MonoBehaviour /// Pauses or resumes local gameplay for a full-screen modal overlay (the online session panel, opened /// with Esc in the lobby/map). Pausing frees the OS cursor and suppresses ALL local input - movement, /// painting, camera look and the mode-switch key - WITHOUT tearing down the mode cycle, so resuming - /// re-enters the exact mode that was active and restores its camera/cursor state. It mirrors the - /// cursor handling (Exit the active mode, then park the orbit rig in - /// Disabled so it stops re-grabbing the cursor every frame) but is reversible. No-op if unchanged. + /// re-enters the exact mode that was active and restores its camera/cursor state. + /// + /// Crucially it does NOT Exit the active mode while pausing: the First-Person / Free-Cam rigs keep their + /// CinemachineCamera at its live priority, so the view stays frozen exactly where it is instead of + /// blending back to the orbit camera (the camera "jump" when the menu opened). Pausing therefore only + /// disables each rig's per-frame look input - dropping the controller's enabled freezes its look + /// without touching its priority - and parks the orbit rig in Disabled so it stops re-grabbing the cursor + /// every frame. Resuming re-runs the same mode's Enter(); because no priority was lowered, that mode's + /// snap-to-current-view is a no-op, so there is no jump on close either. No-op if unchanged. /// public void SetPaused(bool paused) { @@ -267,14 +273,18 @@ public class GameModeManager : MonoBehaviour if (paused) { _resumeIndex = _activeIndex; - ActiveMode?.Exit(); // undo any FreeCam/First-Person takeover (also releases the cursor) - _activeIndex = -1; + _activeIndex = -1; // bookkeeping: no live mode while paused (Tick won't run) - // Painting and movement run off their own flags/Update loops and the orbit rig re-asserts the - // cursor each frame from its LookMode, so stop them all explicitly, then free the cursor. A - // Disabled look-mode keeps the cursor free every frame (the same trick ReleaseToNoPlayer uses). + // Freeze every input source but leave the active camera rig untouched (priority unchanged) so the + // view stays put. Painting/movement run off their own flags; the FP/freecam rigs drive their own + // CinemachineCamera each frame, so dropping their `enabled` freezes the look in place WITHOUT + // lowering priority; the orbit rig re-asserts the cursor each frame from its LookMode, so a + // Disabled look-mode keeps the cursor free every frame. At most one camera rig is ever enabled, + // so disabling both here is safe regardless of which mode was active. if (player) player.ControlEnabled = false; if (painter) painter.PaintingEnabled = false; + if (firstPerson) firstPerson.enabled = false; + if (freeCam) freeCam.enabled = false; if (cameraInput) { cameraInput.enabled = true; @@ -290,7 +300,14 @@ public class GameModeManager : MonoBehaviour int resume = _resumeIndex; _resumeIndex = -1; if (resume >= 0 && resume < _modes.Count) - SwitchTo(resume); // re-Enter restores player/painter/look + cursor (+ re-shows the HUD) + { + // Re-Enter the SAME mode (it was never Exited). The active rig still holds the current view, + // so Enter()'s sync-to-current-view is a no-op -> no jump. Enter restores control/painting/ + // look + cursor and re-shows the HUD. + _activeIndex = resume; + ActiveMode.Enter(); + ModeChanged?.Invoke(ActiveMode); + } else ModeChanged?.Invoke(ActiveMode); }