Main scene gets a full-rect Background image (Chameleon Background 1) in
the menu UI and re-enables a UI component. Lobby scene receives extensive
authoring (sky, lighting, props). New Lobby Sky and White Glow materials;
Yellow Glow emission toned down from ~89 to 64.
The debounced auto-save compared painter values against the on-disk
baseline, so after any slider/toggle change the values stayed different
every frame and the 0.5s timer was pushed forward endlessly, never
firing. Saving only happened via the direct drag-end path. Compare
against the previous-frame snapshot instead so the timer fires once the
values settle. Also pin hudSaveId to a stable key so the layout is
shared across scenes instead of split per-scene.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MouseSensitivity is a static, PlayerPrefs-backed multiplier (default 1,
clamped 0.1-4.0) that scales the mouse-look delta in the FreeCam,
FirstPerson and ThirdPerson controllers. Writes flush immediately so the
value survives a hard build exit. MouseSensitivitySlider binds the
Settings-panel slider to it (range read from the inspector) and mirrors
the value into its label, syncing on panel open via OnEnable.
Main.unity now contains the session-manager canvas directly (the
Online Session Manager prefab was unpacked) and wires the slider binder.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Panel shows in Main while disconnected, auto-hides once a connection is
established, and toggles open/closed with Escape in the Lobby or on a Map.
- Escape now pauses gameplay (active mode exits, cursor freed, paint and
movement disabled) instead of ending the match directly; closing restores
the prior mode via SwitchTo.
- Disconnect button is context-aware: leaves the session in the Lobby, acts
as "Back to Lobby" (EndMatch) for the match authority on a Map, and stays a
plain disconnect for non-authority clients on a Map.
- Removed the Escape->EndMatch handler from MatchManager; match end now routes
through RequestEndMatch with the same authority routing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Players can now host and join over the internet without port-forwarding
via Unity Gaming Services Relay + Lobby, exposed through the unified
Multiplayer Services SDK (Sessions API).
- OnlineSessionManager: anonymous auth, CreateSessionAsync (public,
relay-backed), QuerySessionsAsync server browser, JoinSessionByIdAsync,
and session leave wired into the existing net-stop teardown.
- Per-install auth profile derived from the project path
(mirror_<sha1(dataPath)>) so junction-mirror clones get distinct UGS
player ids, avoiding the same-machine 409 LobbyConflict on join.
- Install com.unity.services.multiplayer 2.2.4 (pulls Relay/Lobby/
Authentication/Core) and attach OnlineSessionManager to the
NetworkManager in Main.
Loopback dev flow (NetworkBootstrap H/C/J/K) is left untouched; the
online path is additive. MatchManager and gameplay are unchanged since
Sessions starts the host/client through NGO as before.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mid-match joiners now spawn a dedicated empty Spectator prefab (NetworkObject
+ SpectatorSetup only) instead of a fully stripped Player prefab. The FreeCam
rig is a standalone scene object in Main, so the spectator needs no avatar body,
renderer, collider, or CharacterController -- eliminating the leftover-body
artifact and the fragile per-peer strip path entirely.
- SpectatorSetup.cs (new): owner binds GameModeManager.BindSpectator (FreeCam-only)
- Spectator.prefab (new): empty avatar (Transform + NetworkObject + SpectatorSetup),
registered in DefaultNetworkPrefabs, wired on MatchManager in Main
- GameModeManager: add BindSpectator/BuildSpectatorModes; drop the spectator
branch from BindLocalPlayer; ReleaseToNoPlayer frees the cursor on teardown
- MatchManager: independent entropy-seeded RNG for fair hunter pick (was sharing
the global engine RNG and always landing on the same client); spawn the
spectator prefab for mid-match joiners; cursor-safe return-to-Main teardown
- FreeCamController: guard IgnorePlayerCollision against a disabled capsule
Also bundled (unrelated user asset/UI edits): PaintHudPanel layout tuning,
font atlas (arialroundedmtprocyr_bold SDF), forestpack_foliage material.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the connection-approval role selection with a server-authoritative
match flow built on NGO additive scene management:
- Scenes: Main is the persistent foundation (NetworkManager, GameModeManager,
cameras, HUD); Lobby and Test Map load/unload additively. Add Lobby + Test Map
to the build settings; remove the obsolete SampleScene.
- MatchManager (plain MonoBehaviour singleton): loads Lobby on server start,
StartMatchTrigger lets the host start the match, rolls one random Hunter (rest
Hider), swaps Lobby -> Test Map (strictly serialized per NGO), respawns each
player as its role variant. Forces additive client sync mode so clients keep
Main instead of single-loading it (fixes "Destination scene is not valid").
- Server-driven spawning: null out NetworkConfig.PlayerPrefab at runtime to
disable auto-spawn, then spawn players after the lobby floor exists (fixes
falling through the floor) with double-spawn and transition guards.
- StartMatchTrigger: server-gated OnTriggerEnter, only the host's own player
starts the match.
- NetworkBootstrap: drop role selection / connection approval; everyone spawns
as the neutral Player prefab. Host/Client/Server/Shutdown buttons stay.
- NetworkPlayerSetup.ScopedModes flag (baked on Hunter/Hider prefabs): lobby
avatar gets the full mode set, match variants get the role-scoped set.
- GameModeManager.BindLocalPlayer reads ScopedModes and rebinds the painter
unconditionally (fixes stale painter binding on respawn -> brush painting in
every mode).
- MeshPainter.PaintingEnabled defaults to false (unbound/pre-spawn/remote never
paints); PaintHud visibility now also gates on a bound painter (fixes the HUD
showing at startup before any avatar exists).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>