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>
23 lines
978 B
C#
23 lines
978 B
C#
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Per-avatar glue for a mid-match SPECTATOR. The spectator object is deliberately empty - no body, no
|
|
/// renderer, no collider, no controller - because the free-fly camera is a separate, persistent scene
|
|
/// object (in Main) that drives its own rig off Camera.main and needs nothing from this avatar. So the
|
|
/// spectator only has to exist as the owner's player object and flip the local mode set to free-cam-only.
|
|
/// The owner does that here; remote peers do nothing (there is no body to show or simulate). When the
|
|
/// host ends the match, MatchManager respawns this client as a neutral lobby Player.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class SpectatorSetup : NetworkBehaviour
|
|
{
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (!IsOwner) return;
|
|
|
|
var manager = FindFirstObjectByType<GameModeManager>(FindObjectsInactive.Include);
|
|
if (manager) manager.BindSpectator();
|
|
}
|
|
}
|