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 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-06-28 15:51:39 +02:00
1 parent 3f58e75623
commit f11fbc8c1c
1 file changed
+26 -9
+26 -9
View File
@@ -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
/// <see cref="ReleaseToNoPlayer"/> 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 <c>enabled</c> 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.
/// </summary>
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);
}