Refactor Assets/Scripts: trim restating comments, minor structure cleanups
Sweep over 48 files (Editor/ excluded): remove comments that restate the code, condense class summaries, fix three stale doc statements (HsvColorPicker alpha bar, PaintHud layoutPrefab, MasterVolume FallbackDefault). Inline two single-use wrappers (IsPointerOverUi, BuildModes), drop an unused using, replace a magic literal with the existing ParallaxBase constant, and convert ~10 UnityEngine.Object null checks to the implicit-bool convention. No serialized fields, signatures, RPC/NetworkVariable names, defaults, or #if blocks touched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eeee5fc2f0
commit
6c03e5d3f6
48 files changed
+289
-481
No files matched your search
@@ -5,12 +5,9 @@ using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Dev-only connection harness for local multiplayer testing across the junction-mirror clones: one
|
||||
/// instance clicks Host and the others click Client (loopback 127.0.0.1 via the configured
|
||||
/// UnityTransport). Everyone spawns as the neutral Player prefab into the Lobby; roles (Hunter/Hider)
|
||||
/// are rolled and applied by <see cref="MatchManager"/> when the match starts, not here. Hotkeys:
|
||||
/// H = Host, C = Client, J = Server, K = Shutdown. Purely a testing scaffold - replace with real
|
||||
/// lobby/menu UI later. Attach to the same GameObject as the NetworkManager.
|
||||
/// Dev-only connection harness for local multiplayer testing: Host/Client/Server over loopback via the
|
||||
/// configured UnityTransport (hotkeys H/C/J, K = Shutdown). Roles are rolled by <see cref="MatchManager"/>
|
||||
/// at match start, not here. Testing scaffold only - replace with real lobby/menu UI later.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NetworkManager))]
|
||||
[DisallowMultipleComponent]
|
||||
@@ -41,7 +38,7 @@ public class NetworkBootstrap : MonoBehaviour
|
||||
if (TypingGuard.IsTyping) return; // don't fire H/C/J/K while typing in a text field
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
var kb = Keyboard.current;
|
||||
if (kb == null || _net == null) return;
|
||||
if (kb == null || !_net) return;
|
||||
if (!_net.IsListening)
|
||||
{
|
||||
if (kb.hKey.wasPressedThisFrame) _net.StartHost();
|
||||
@@ -57,7 +54,7 @@ public class NetworkBootstrap : MonoBehaviour
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!showGui || _net == null) return;
|
||||
if (!showGui || !_net) return;
|
||||
|
||||
GUILayout.BeginArea(new Rect(10, 10, 220, 160), GUI.skin.box);
|
||||
if (!_net.IsListening)
|
||||
|
||||
@@ -307,7 +307,7 @@ public class MatchManager : MonoBehaviour
|
||||
|
||||
// Disable NGO auto-spawn (decided purely by PlayerPrefab != null); keep the reference and spawn
|
||||
// manually once a floored scene exists. Runtime-only mutation - no asset diff.
|
||||
if (_net != null)
|
||||
if (_net)
|
||||
{
|
||||
_playerPrefab = _net.NetworkConfig.PlayerPrefab;
|
||||
_net.NetworkConfig.PlayerPrefab = null;
|
||||
@@ -337,7 +337,6 @@ public class MatchManager : MonoBehaviour
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
|
||||
// Unhooks the per-session callbacks and named-message handlers (shared by OnDisable and OnNetStopped).
|
||||
private void UnhookSessionCallbacks()
|
||||
{
|
||||
_net.OnClientConnectedCallback -= OnClientConnected;
|
||||
@@ -455,7 +454,7 @@ public class MatchManager : MonoBehaviour
|
||||
|
||||
private void HookSceneManager()
|
||||
{
|
||||
if (_hooked || _net == null || _net.SceneManager == null) return;
|
||||
if (_hooked || !_net || _net.SceneManager == null) return;
|
||||
_net.SceneManager.OnSceneEvent += OnSceneEvent;
|
||||
_hooked = true;
|
||||
}
|
||||
@@ -483,7 +482,7 @@ public class MatchManager : MonoBehaviour
|
||||
// the load/respawn routine covers it (the PlayerObject guard in SpawnFor prevents a double spawn).
|
||||
private void OnClientConnected(ulong clientId)
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
|
||||
// Dedicated-server case: the first client to connect becomes the match authority (a host already
|
||||
// claimed it at server start). Told via named message so it reads Esc locally.
|
||||
@@ -514,7 +513,7 @@ public class MatchManager : MonoBehaviour
|
||||
// dedicated-server match stays controllable.
|
||||
private void OnClientDisconnected(ulong clientId)
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
|
||||
// A hider that leaves mid-match can never be found - drop it so "all hiders found" can still trigger.
|
||||
_pendingHiders.Remove(clientId);
|
||||
@@ -545,7 +544,7 @@ public class MatchManager : MonoBehaviour
|
||||
// the server, so it records its own identity directly; a pure client reports it to the server by message.
|
||||
private void OnLocalClientConnected(ulong clientId)
|
||||
{
|
||||
if (_net == null || clientId != _net.LocalClientId) return;
|
||||
if (!_net || clientId != _net.LocalClientId) return;
|
||||
|
||||
if (_net.IsServer) RegisterIdentity(_net.LocalClientId, PersistentPlayerId.Value);
|
||||
else SendIdentityToServer(PersistentPlayerId.Value);
|
||||
@@ -554,7 +553,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Client -> server: report this install's persistent id so the server can map it to our ephemeral clientId.
|
||||
private void SendIdentityToServer(string persistentId)
|
||||
{
|
||||
var cmm = _net != null ? _net.CustomMessagingManager : null;
|
||||
var cmm = _net ? _net.CustomMessagingManager : null;
|
||||
if (cmm == null || string.IsNullOrEmpty(persistentId)) return;
|
||||
// Grows up to the cap if a future id source is longer than the initial buffer (persistent ids are short).
|
||||
using (var writer = new FastBufferWriter(256, Allocator.Temp, 1024))
|
||||
@@ -568,7 +567,7 @@ public class MatchManager : MonoBehaviour
|
||||
private void OnIdentityMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
reader.ReadValueSafe(out string persistentId);
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
RegisterIdentity(senderClientId, persistentId);
|
||||
}
|
||||
|
||||
@@ -605,8 +604,8 @@ public class MatchManager : MonoBehaviour
|
||||
/// Safe to call repeatedly (only acts once, while still in the lobby phase).</summary>
|
||||
public void StartMatch()
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (Phase != MatchPhase.Lobby) return; // double-start / not-in-lobby guard
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (Phase != MatchPhase.Lobby) return;
|
||||
if (!hunterPrefab || !hiderPrefab)
|
||||
{
|
||||
Debug.LogError("[MatchManager] Role prefabs not assigned - cannot start match.", this);
|
||||
@@ -730,7 +729,6 @@ public class MatchManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// Waits up to 'seconds' of server real time, returning early the moment 'until' (if supplied) is true.
|
||||
private IEnumerator WaitPhase(float seconds, System.Func<bool> until)
|
||||
{
|
||||
_skipPhase = false; // drop a stale debug-skip from the previous phase; only this phase may set it
|
||||
@@ -760,7 +758,7 @@ public class MatchManager : MonoBehaviour
|
||||
[ContextMenu("Next Sub-Phase (Debug)")]
|
||||
public void DebugSkipToNextSubPhase()
|
||||
{
|
||||
if (_net == null) return;
|
||||
if (!_net) return;
|
||||
if (_net.IsServer) { DebugSkipServer(); return; }
|
||||
if (_isLocalAuthority) SendEmptyNamedMessage(MsgDebugSkip, NetworkManager.ServerClientId);
|
||||
}
|
||||
@@ -768,7 +766,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Server-only. Flags the running phase-wait loop to break early so RunMatchPhases moves to the next sub-phase.
|
||||
private void DebugSkipServer()
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (_subPhase == MatchSubPhase.None) return; // nothing running to skip
|
||||
_skipPhase = true;
|
||||
Debug.Log($"[MatchManager] DEBUG: skipping the rest of {_subPhase}.", this);
|
||||
@@ -777,7 +775,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Server handler: an authority client asked to skip to the next sub-phase.
|
||||
private void OnDebugSkipMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (!IsMatchAuthority(senderClientId)) return;
|
||||
DebugSkipServer();
|
||||
}
|
||||
@@ -859,7 +857,7 @@ public class MatchManager : MonoBehaviour
|
||||
// applied paint cutoff - exactly the condition the per-client reveal uses to un-hide the body.
|
||||
private bool LocalClientReady(List<ulong> ids)
|
||||
{
|
||||
var sm = _net != null ? _net.SpawnManager : null;
|
||||
var sm = _net ? _net.SpawnManager : null;
|
||||
if (sm == null) return false;
|
||||
for (int i = 0; i < ids.Count; i++)
|
||||
{
|
||||
@@ -873,7 +871,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Server -> every other client: the target ids + holding phase + generation for this barrier round.
|
||||
private void BroadcastBeginLoad(MatchSubPhase activePhase)
|
||||
{
|
||||
var cmm = _net != null ? _net.CustomMessagingManager : null;
|
||||
var cmm = _net ? _net.CustomMessagingManager : null;
|
||||
if (cmm == null) return;
|
||||
|
||||
_loadRecipients.Clear();
|
||||
@@ -932,7 +930,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Client -> server: this machine finished loading (echoes the generation so a stale reply is ignored).
|
||||
private void SendReadyToServer(int generation)
|
||||
{
|
||||
var cmm = _net != null ? _net.CustomMessagingManager : null;
|
||||
var cmm = _net ? _net.CustomMessagingManager : null;
|
||||
if (cmm == null) return;
|
||||
using (var writer = new FastBufferWriter(sizeof(int), Allocator.Temp))
|
||||
{
|
||||
@@ -945,19 +943,17 @@ public class MatchManager : MonoBehaviour
|
||||
private void OnReadyMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
reader.ReadValueSafe(out int generation);
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (generation != _loadGeneration) return; // stale ack from a previous barrier round
|
||||
_readyClients.Add(senderClientId);
|
||||
}
|
||||
|
||||
// Server-only. Applies the sub-phase to the server's own mirror and broadcasts it to every other client.
|
||||
private void SetPhaseServer(MatchSubPhase phase, float duration)
|
||||
{
|
||||
ApplyPhaseLocal(phase, duration, matchMode);
|
||||
BroadcastPhase(phase, duration, matchMode, 0, true);
|
||||
}
|
||||
|
||||
// Sets this machine's sub-phase mirror + countdown + mode (followers poll LocalSubPhase).
|
||||
// Shared by the server's SetPhaseServer and a client's OnPhaseMessage handler.
|
||||
private void ApplyPhaseLocal(MatchSubPhase phase, float duration, MatchMode mode)
|
||||
{
|
||||
@@ -987,7 +983,7 @@ public class MatchManager : MonoBehaviour
|
||||
// (which applied it directly in SetPhaseServer, so it must not double-apply via loopback).
|
||||
private void BroadcastPhase(MatchSubPhase phase, float duration, MatchMode mode, ulong targetClient, bool toAll)
|
||||
{
|
||||
var cmm = _net != null ? _net.CustomMessagingManager : null;
|
||||
var cmm = _net ? _net.CustomMessagingManager : null;
|
||||
if (cmm == null) return;
|
||||
using (var writer = new FastBufferWriter(sizeof(byte) + sizeof(float) + sizeof(byte), Allocator.Temp))
|
||||
{
|
||||
@@ -1023,7 +1019,7 @@ public class MatchManager : MonoBehaviour
|
||||
// locally (no loopback message, mirroring SetPhaseServer). Hiders and spectators never receive a ping.
|
||||
private void BroadcastRadarPings()
|
||||
{
|
||||
if (_net == null || !_net.IsServer || _pendingHiders.Count == 0) return;
|
||||
if (!_net || !_net.IsServer || _pendingHiders.Count == 0) return;
|
||||
|
||||
_radarPingIds.Clear();
|
||||
foreach (ulong hiderClientId in _pendingHiders)
|
||||
@@ -1067,7 +1063,7 @@ public class MatchManager : MonoBehaviour
|
||||
/// directly. No-op outside the Seek phase.</summary>
|
||||
public void RequestManualPing()
|
||||
{
|
||||
if (_net == null || _subPhase != MatchSubPhase.Seek) return;
|
||||
if (!_net || _subPhase != MatchSubPhase.Seek) return;
|
||||
|
||||
if (_net.IsServer) { ServerManualPing(_net.LocalClientId); return; }
|
||||
SendEmptyNamedMessage(MsgManualPing, NetworkManager.ServerClientId);
|
||||
@@ -1077,7 +1073,7 @@ public class MatchManager : MonoBehaviour
|
||||
// ServerManualPing validates it is a live hider during Seek.
|
||||
private void OnManualPingMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
ServerManualPing(senderClientId);
|
||||
}
|
||||
|
||||
@@ -1099,7 +1095,7 @@ public class MatchManager : MonoBehaviour
|
||||
private void SpawnRadarBlipsLocal()
|
||||
{
|
||||
var radar = Radar.Instance;
|
||||
var spawnMgr = _net != null ? _net.SpawnManager : null;
|
||||
var spawnMgr = _net ? _net.SpawnManager : null;
|
||||
if (!radar || spawnMgr == null) return;
|
||||
for (int i = 0; i < _radarPingIds.Count; i++)
|
||||
if (spawnMgr.SpawnedObjects.TryGetValue(_radarPingIds[i], out var no) && no)
|
||||
@@ -1113,7 +1109,7 @@ public class MatchManager : MonoBehaviour
|
||||
reader.ReadValueSafe(out float lifetime);
|
||||
reader.ReadValueSafe(out int count);
|
||||
var radar = Radar.Instance;
|
||||
var spawnMgr = _net != null ? _net.SpawnManager : null;
|
||||
var spawnMgr = _net ? _net.SpawnManager : null;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
reader.ReadValueSafe(out ulong netObjId);
|
||||
@@ -1128,7 +1124,7 @@ public class MatchManager : MonoBehaviour
|
||||
/// applies directly. No-op outside the seek phase.</summary>
|
||||
public void ReportHit(ulong targetClientId)
|
||||
{
|
||||
if (_net == null || _subPhase != MatchSubPhase.Seek) return;
|
||||
if (!_net || _subPhase != MatchSubPhase.Seek) return;
|
||||
|
||||
if (_net.IsServer)
|
||||
{
|
||||
@@ -1152,7 +1148,7 @@ public class MatchManager : MonoBehaviour
|
||||
private void OnReportHitMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
reader.ReadValueSafe(out ulong targetClientId);
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (_subPhase != MatchSubPhase.Seek) return;
|
||||
if (!_pendingHiders.Contains(targetClientId)) return; // not a live (un-found) hider
|
||||
if (!IsHunter(senderClientId)) return; // only a hunter may shoot
|
||||
@@ -1186,7 +1182,7 @@ public class MatchManager : MonoBehaviour
|
||||
if (hitRevealDelay > 0f) yield return new WaitForSeconds(hitRevealDelay);
|
||||
|
||||
_revealingHiders.Remove(hiderClientId);
|
||||
if (_net == null || !_net.IsServer) yield break;
|
||||
if (!_net || !_net.IsServer) yield break;
|
||||
|
||||
_pendingHiders.Remove(hiderClientId);
|
||||
|
||||
@@ -1280,7 +1276,6 @@ public class MatchManager : MonoBehaviour
|
||||
_conversionRecords.Clear();
|
||||
}
|
||||
|
||||
// Server-only. Despawns every live conversion statue (match ending / back to lobby) and drops the list.
|
||||
private void DespawnConversionStatues()
|
||||
{
|
||||
for (int i = 0; i < _statues.Count; i++)
|
||||
@@ -1291,7 +1286,6 @@ public class MatchManager : MonoBehaviour
|
||||
_statues.Clear();
|
||||
}
|
||||
|
||||
// True if the client's current avatar is a Hunter role variant (used to gate shooting server-side).
|
||||
private bool IsHunter(ulong clientId)
|
||||
{
|
||||
if (!_net.ConnectedClients.TryGetValue(clientId, out var c) || !c.PlayerObject) return false;
|
||||
@@ -1303,7 +1297,7 @@ public class MatchManager : MonoBehaviour
|
||||
/// neutral lobby Player (including any spectator-held mid-match joiners). Only acts while in a match.</summary>
|
||||
public void EndMatch()
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (Phase != MatchPhase.InMatch) return; // only endable mid-match
|
||||
|
||||
// Stop the sub-phase machine if the match is being ended early (authority's Back-to-Lobby) and clear
|
||||
@@ -1329,8 +1323,6 @@ public class MatchManager : MonoBehaviour
|
||||
Debug.Log("[MatchManager] Back in lobby.", this);
|
||||
}
|
||||
|
||||
// Unloads one gameplay scene (if loaded), then additively loads the next (shared by the match
|
||||
// start/end sequences).
|
||||
private IEnumerator SwapScenes(string unloadSceneName, string loadSceneName)
|
||||
{
|
||||
var sm = _net.SceneManager;
|
||||
@@ -1366,9 +1358,8 @@ public class MatchManager : MonoBehaviour
|
||||
_net.SceneManager.OnSceneEvent -= OnEvt;
|
||||
}
|
||||
|
||||
// Despawns each connected client's current avatar (if any) and spawns the prefab chosen by
|
||||
// prefabFor at the given position. Used for both lobby->match (role variants) and match->lobby
|
||||
// (neutral Player); the latter also gives spectator-held joiners their first avatar.
|
||||
// Used for both lobby->match (role variants) and match->lobby (neutral Player); the latter also
|
||||
// gives spectator-held joiners their first avatar.
|
||||
private void RespawnAll(System.Func<ulong, GameObject> prefabFor, Vector3 at)
|
||||
{
|
||||
var ids = new List<ulong>(_net.ConnectedClientsIds);
|
||||
@@ -1437,7 +1428,7 @@ public class MatchManager : MonoBehaviour
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_net == null) return false;
|
||||
if (!_net) return false;
|
||||
if (_net.IsServer) return IsMatchAuthority(_net.LocalClientId);
|
||||
return _isLocalAuthority;
|
||||
}
|
||||
@@ -1448,7 +1439,7 @@ public class MatchManager : MonoBehaviour
|
||||
/// the authority or no match is running.</summary>
|
||||
public void RequestEndMatch()
|
||||
{
|
||||
if (_net == null) return;
|
||||
if (!_net) return;
|
||||
if (_net.IsServer) { EndMatch(); return; } // EndMatch itself guards Phase == InMatch
|
||||
if (_isLocalAuthority) RequestEndMatchFromServer();
|
||||
}
|
||||
@@ -1480,7 +1471,7 @@ public class MatchManager : MonoBehaviour
|
||||
// so a single dummy byte is written).
|
||||
private void SendEmptyNamedMessage(string messageName, ulong targetClientId)
|
||||
{
|
||||
var cmm = _net != null ? _net.CustomMessagingManager : null;
|
||||
var cmm = _net ? _net.CustomMessagingManager : null;
|
||||
if (cmm == null) return;
|
||||
using (var writer = new FastBufferWriter(sizeof(byte), Allocator.Temp))
|
||||
{
|
||||
@@ -1506,7 +1497,7 @@ public class MatchManager : MonoBehaviour
|
||||
// Server handler: an authority client asked to end the match.
|
||||
private void OnRequestEndMatchMessage(ulong senderClientId, FastBufferReader reader)
|
||||
{
|
||||
if (_net == null || !_net.IsServer) return;
|
||||
if (!_net || !_net.IsServer) return;
|
||||
if (!IsMatchAuthority(senderClientId)) return;
|
||||
EndMatch(); // guards Phase == InMatch itself
|
||||
}
|
||||
|
||||
@@ -5,25 +5,16 @@ using Chameleon.Components;
|
||||
|
||||
/// <summary>
|
||||
/// A frozen, painted "statue" of a hider at the exact spot / stance / painting it held the moment it was
|
||||
/// CONVERTED into a hunter (Conversion mode only). <see cref="MatchManager"/> captures those on the
|
||||
/// conversion and spawns one statue per converted hider at the start of the Resolution phase, so every
|
||||
/// player sees where each hider was caught as a faithful representation (same skinned body, camo painting
|
||||
/// and fur) - independent of the now-hunter avatar, which has long since moved on.
|
||||
/// CONVERTED into a hunter (Conversion mode only); <see cref="MatchManager"/> captures those on the
|
||||
/// conversion and spawns one statue per converted hider at Resolution start. Purely presentational (no
|
||||
/// controller / collision / role) and a dedicated prefab, NOT a <see cref="NetworkPlayerSetup"/> avatar -
|
||||
/// so it never pollutes the scoreboard, per-client visibility matrix or resolution X-ray reveal.
|
||||
///
|
||||
/// Purely presentational: no controller, no collision, no gameplay role. It is a dedicated prefab (NOT a
|
||||
/// <see cref="NetworkPlayerSetup"/> avatar), so it never pollutes the scoreboard, per-client visibility
|
||||
/// matrix or resolution X-ray reveal - those all key off NetworkPlayerSetup, which the statue lacks.
|
||||
///
|
||||
/// Server-owned. Three replicated ingredients rebuild it identically on every client:
|
||||
/// <list type="bullet">
|
||||
/// <item><b>Transform</b> - the server Instantiates it at the captured pos/rot; the (server-authoritative)
|
||||
/// NetworkTransform replicates that.</item>
|
||||
/// <item><b>Painting</b> - rides the existing <see cref="PlayerPaintSync"/> snapshot transfer; this object
|
||||
/// drives the push explicitly (server loads the captured snapshot, then broadcasts it), and PlayerPaintSync
|
||||
/// suppresses its own auto pull/publish for a statue receiver so the two never race.</item>
|
||||
/// <item><b>Stance</b> - a single replicated pose index the pose controller reproduces (network-driven),
|
||||
/// then freezes.</item>
|
||||
/// </list>
|
||||
/// Server-owned; three replicated ingredients rebuild it identically on every client: transform
|
||||
/// (server-authoritative NetworkTransform), painting (rides the existing <see cref="PlayerPaintSync"/>
|
||||
/// snapshot transfer, pushed explicitly by the server - PlayerPaintSync suppresses its own auto
|
||||
/// pull/publish for a statue receiver so the two never race) and stance (a replicated pose index the
|
||||
/// pose controller reproduces, then freezes).
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class MatchStatue : NetworkBehaviour
|
||||
|
||||
@@ -7,7 +7,6 @@ using Chameleon.Components;
|
||||
/// Per-avatar network glue on the spawned player. The local owner binds the scene singletons
|
||||
/// (GameModeManager, cameras) to itself via <see cref="GameModeManager.BindLocalPlayer"/>; remote
|
||||
/// avatars stop simulating so their transform is driven purely by the NetworkTransform replication.
|
||||
/// Position-sync milestone: remote avatars still show their mesh/idle pose, just no local control.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(PlayerCharacterController))]
|
||||
[DisallowMultipleComponent]
|
||||
@@ -297,7 +296,6 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
SetBodyRenderers(visible);
|
||||
}
|
||||
|
||||
// Toggles every body renderer and records the applied state for the change-guard above.
|
||||
private void SetBodyRenderers(bool visible)
|
||||
{
|
||||
if (_bodyRenderers != null)
|
||||
|
||||
@@ -9,25 +9,17 @@ using Unity.Services.Multiplayer;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Online hosting/joining over Unity Gaming Services so players can connect across the internet
|
||||
/// without port forwarding. Uses the unified Multiplayer Services "Sessions" API, which bundles
|
||||
/// Relay (NAT-free messaging via Unity's relay servers) + Lobby (the public server list) + anonymous
|
||||
/// Authentication behind single calls, and configures + starts the NGO transport itself - so we do
|
||||
/// NOT call <see cref="NetworkManager.StartHost"/>/<c>StartClient</c> here; CreateSessionAsync starts
|
||||
/// the host and JoinSession* starts the client.
|
||||
/// Online hosting/joining over Unity Gaming Services (unified Multiplayer "Sessions" API: Relay + Lobby +
|
||||
/// anonymous Authentication behind single calls). The Sessions API configures and starts the NGO transport
|
||||
/// itself, so we do NOT call <see cref="NetworkManager.StartHost"/>/<c>StartClient</c> here -
|
||||
/// CreateSessionAsync starts the host, JoinSession* starts the client; the usual NetworkManager callbacks
|
||||
/// then fire exactly as for loopback hosting, so MatchManager, spawning and authority are unaffected.
|
||||
/// Note the UGS "session" (the public server-list entry) is distinct from the in-game "Lobby" scene.
|
||||
///
|
||||
/// Terminology: the UGS "session" is the entry in the public server list (network layer). It is a
|
||||
/// different thing from the in-game "Lobby" scene (the pre-match staging area that <see cref="MatchManager"/>
|
||||
/// loads after the connection is up). This component does not touch the match flow at all - the usual
|
||||
/// NetworkManager callbacks fire exactly as they do for loopback hosting, so MatchManager, spawning and
|
||||
/// authority are unaffected.
|
||||
///
|
||||
/// This is the logic layer only: state + async host/refresh/join/disconnect calls, surfaced through the
|
||||
/// <see cref="Changed"/>/<see cref="SessionsChanged"/> events. The uGUI server browser that drives it lives
|
||||
/// on its own canvas (<see cref="OnlineSessionBrowserUI"/>); this component carries no UI of its own.
|
||||
/// Requires the project to be linked to a UGS cloud project (Project Settings > Services) with Relay,
|
||||
/// Lobby and Authentication (Anonymous) enabled; otherwise sign-in fails with a clear status message.
|
||||
/// Attach to the same GameObject as the NetworkManager.
|
||||
/// Logic layer only, surfaced through the <see cref="Changed"/>/<see cref="SessionsChanged"/> events; the
|
||||
/// uGUI browser driving it is <see cref="OnlineSessionBrowserUI"/>. Requires the project to be linked to a
|
||||
/// UGS cloud project (Project Settings > Services) with Relay, Lobby and Authentication (Anonymous)
|
||||
/// enabled; otherwise sign-in fails with a clear status message.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NetworkManager))]
|
||||
[DisallowMultipleComponent]
|
||||
@@ -122,7 +114,7 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task EnsureSignedInAsync()
|
||||
private async Task EnsureSignedInAsync()
|
||||
{
|
||||
if (UnityServices.State != ServicesInitializationState.Initialized)
|
||||
{
|
||||
@@ -156,7 +148,7 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
// Shared busy/sign-in/error skeleton around one session operation; the body carries the
|
||||
// op-specific statuses and state. ownsConnection = the op starts NGO (host/join), so a timeout that
|
||||
// left the transport half-up must tear it down.
|
||||
private async System.Threading.Tasks.Task RunSessionOpAsync(string failLabel, bool ownsConnection, Func<System.Threading.Tasks.Task> body)
|
||||
private async Task RunSessionOpAsync(string failLabel, bool ownsConnection, Func<Task> body)
|
||||
{
|
||||
SetBusy(true);
|
||||
try
|
||||
|
||||
@@ -2,19 +2,11 @@ using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Replicates the visual body state that the disabled-on-remote controller / pose system would
|
||||
/// otherwise drive: the owner publishes its selected pose index, resolved locomotion category
|
||||
/// (idle / walk / run / fall) AND the wall-lean / ground-raise / ceiling mesh offset, so a remote
|
||||
/// avatar shows the same pose, walk/run/fall animation and leans into walls / raises off the ground
|
||||
/// like the owner — not just a sliding, upright idle.
|
||||
///
|
||||
/// Body position/rotation come from the NetworkTransform; this only carries the small extra state on
|
||||
/// top. Pose index and locomotion change rarely (a pose cycle, a locomotion transition), so those
|
||||
/// NetworkVariables send a delta only when the value actually changes. The mesh offset is the visual
|
||||
/// model's child-local position (<see cref="PlayerCharacterController.MeshOffsetTarget"/>) — a tiny
|
||||
/// vector the owner eases continuously; the remote eases onto the replicated value so it doesn't
|
||||
/// tick-step (the body itself is already interpolated by the NetworkTransform).
|
||||
///
|
||||
/// Replicates the visual body state the disabled-on-remote controller / pose system would otherwise
|
||||
/// drive: the owner publishes its pose index, resolved locomotion category and the wall-lean /
|
||||
/// ground-raise mesh offset (<see cref="PlayerCharacterController.MeshOffsetTarget"/>), so a remote
|
||||
/// avatar animates like the owner instead of sliding in an upright idle. Body position/rotation come
|
||||
/// from the NetworkTransform; the remote eases onto the replicated mesh offset so it doesn't tick-step.
|
||||
/// Runs after the PlayerPoseController (execution order 100) so the owner reads this frame's resolved
|
||||
/// state; remote avatars apply via OnValueChanged / per-frame easing, independent of frame order.
|
||||
/// </summary>
|
||||
|
||||
@@ -607,7 +607,7 @@ public class PlayerPaintSync : NetworkBehaviour
|
||||
CopyChunkInto(_snapBuffer, offset, chunk);
|
||||
}
|
||||
|
||||
/// <summary>Copies a received chunk into the reassembly buffer, ignoring out-of-bounds offsets.</summary>
|
||||
// Out-of-bounds offsets are ignored rather than thrown on.
|
||||
private static void CopyChunkInto(byte[] buffer, int offset, byte[] chunk)
|
||||
{
|
||||
if (offset >= 0 && offset + chunk.Length <= buffer.Length)
|
||||
@@ -693,7 +693,6 @@ public class PlayerPaintSync : NetworkBehaviour
|
||||
_uploadBuffer = null;
|
||||
}
|
||||
|
||||
/// <summary>All connected client ids except the given one (server-side).</summary>
|
||||
private ulong[] OtherClientIds(ulong except)
|
||||
{
|
||||
var ids = NetworkManager.ConnectedClientsIds;
|
||||
|
||||
@@ -2,12 +2,10 @@ 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.
|
||||
/// Per-avatar glue for a mid-match SPECTATOR. The spectator object is deliberately empty (no body,
|
||||
/// renderer, collider or controller) - the free-fly camera is a separate, persistent scene object in
|
||||
/// Main, so this only has to exist as the owner's player object and flip the local mode set to
|
||||
/// free-cam-only; remote peers do nothing. MatchManager respawns it as a lobby Player at match end.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class SpectatorSetup : NetworkBehaviour
|
||||
|
||||
@@ -2,15 +2,12 @@ using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// On-screen match HUD binder: drives the authored <c>MatchHudCanvas</c> widgets from live match state -
|
||||
/// the current sub-phase + countdown (top centre) and a hunter crosshair during the seek phase. The visual
|
||||
/// layout lives in the scene; this component creates nothing at runtime, it only binds. Attach it to the
|
||||
/// MatchHudCanvas and wire the references in the Inspector.
|
||||
///
|
||||
/// Passive overlay: the authored canvas has no <see cref="UnityEngine.UI.GraphicRaycaster"/> and every graphic
|
||||
/// is raycastTarget=false, so it never consumes pointer events, and its sortingOrder (90) sits below PaintHud's
|
||||
/// (100) so tool panels always win. There is no change event for the phase/timer, so the values are polled once
|
||||
/// per frame; the visible strings are only rebuilt when the displayed second / phase actually changes.
|
||||
/// Binds the authored <c>MatchHudCanvas</c> widgets to live match state (sub-phase + countdowns, role
|
||||
/// counts, hunter crosshair); creates nothing at runtime. Passive overlay: the canvas has no
|
||||
/// <see cref="UnityEngine.UI.GraphicRaycaster"/> and every graphic is raycastTarget=false, and its
|
||||
/// sortingOrder (90) sits below PaintHud's (100) so tool panels always win. There is no change event for
|
||||
/// the phase/timer, so values are polled per frame; the visible strings are only rebuilt when the
|
||||
/// displayed second / phase actually changes.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class MatchHud : MonoBehaviour
|
||||
|
||||
@@ -8,24 +8,16 @@ using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// uGUI binding for <see cref="OnlineSessionManager"/>. Drives the server-browser canvas - Host / Refresh /
|
||||
/// pick a row / Join / Disconnect plus a status line - and mirrors the manager's state through its
|
||||
/// <see cref="OnlineSessionManager.Changed"/> / <see cref="OnlineSessionManager.SessionsChanged"/> events.
|
||||
/// Lives on the browser canvas; the session logic stays on the NetworkManager's
|
||||
/// <see cref="OnlineSessionManager"/>.
|
||||
/// uGUI binding for <see cref="OnlineSessionManager"/>: Host / Refresh / row select / Join / Disconnect
|
||||
/// plus a status line, mirroring the manager through its <see cref="OnlineSessionManager.Changed"/> /
|
||||
/// <see cref="OnlineSessionManager.SessionsChanged"/> events; the session logic stays on the manager.
|
||||
///
|
||||
/// Selection model: Refresh fills the list with clones of <see cref="entryTemplate"/> (each a clickable row
|
||||
/// showing name + player count). Clicking a row selects it; Join connects to the selected session. While
|
||||
/// connected, only Disconnect is interactable.
|
||||
///
|
||||
/// Overlay behaviour: the panel is always shown in Main (not connected). Once a connection is up it hides;
|
||||
/// in the lobby/map Esc toggles it back as a modal pause overlay (cursor freed, local gameplay suspended via
|
||||
/// <see cref="GameModeManager.SetPaused"/>). The Disconnect button is context-sensitive: in Main (not
|
||||
/// connected) it is an application "Exit" (quits the build, or stops play mode in the editor) so the player
|
||||
/// can leave without Alt+F4; on the map it becomes "Back to Lobby" for the match authority (ends the match);
|
||||
/// everyone else (in the lobby, or a non-authority client on the map) gets a plain disconnect. Only the
|
||||
/// visual <see cref="panelRoot"/> is toggled - this binder stays alive on its (always-active) canvas so it
|
||||
/// keeps reading Esc while the panel is hidden.
|
||||
/// The panel is always shown in Main (not connected); once a connection is up it hides, and in the
|
||||
/// lobby/map Esc toggles it back as a modal pause overlay (cursor freed, gameplay suspended via
|
||||
/// <see cref="GameModeManager.SetPaused"/>). The Disconnect button is context-sensitive: in Main it is an
|
||||
/// application "Exit"; on the map it becomes "Back to Lobby" for the match authority (ends the match);
|
||||
/// everyone else gets a plain disconnect. Only the visual <see cref="panelRoot"/> is toggled - this binder
|
||||
/// stays alive on its (always-active) canvas so it keeps reading Esc while the panel is hidden.
|
||||
/// </summary>
|
||||
public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user