Add player-collision toggle and make conversion statues follow it

Add a per-machine "Players Collide" switch on GameModeManager: a
self-healing reconciler routes the local capsule through other avatars'
body colliders via Physics.IgnoreCollision when disabled, re-asserting
every frame while off to survive the late-created runtime MeshCollider,
conversion respawns and teleport resets. Expose Active/ActiveVersion/
BodyCollider on NetworkPlayerSetup for the reconciler.

Give MatchStatue the same Active registry + BodyCollider pattern so the
frozen conversion statues obey the same toggle (they carry their own
paint MeshCollider but are deliberately not NetworkPlayerSetup avatars).
Also drive the statue's steady X-ray reveal in Resolution, matching an
un-found hider.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-07-06 11:17:19 +02:00
1 parent 8bafa2f10a
commit 414beaa403
3 files changed
+142 -1

No files matched your search

@@ -124,6 +124,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
public override void OnNetworkSpawn()
{
_active.Add(this); // scoreboard registry (paired with OnNetworkDespawn)
ActiveVersion++; // signal the player-collision reconciler that the avatar set changed
_bodyRenderers = GetComponentsInChildren<SkinnedMeshRenderer>(true);
_furRenderers = GetComponentsInChildren<FurShellRenderer>(true);
_painter = GetComponentInChildren<MeshPainter>(true);
@@ -193,6 +194,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
public override void OnNetworkDespawn()
{
_active.Remove(this);
ActiveVersion++;
_isFound.OnValueChanged -= OnFoundChanged;
}
@@ -462,6 +464,29 @@ public class NetworkPlayerSetup : NetworkBehaviour
// Conversion hit despawns the hider object and spawns a hunter one, so both sides update from the registry).
private static readonly List<NetworkPlayerSetup> _active = new List<NetworkPlayerSetup>();
/// <summary>Read-only view of all avatars spawned on this machine (the same registry the scoreboard uses).
/// Consumed by the player-collision reconciler to find the bodies the local player should pass through.</summary>
public static IReadOnlyList<NetworkPlayerSetup> Active => _active;
/// <summary>Bumped on every spawn/despawn so a per-frame consumer can cheaply detect a membership change
/// without rescanning the list.</summary>
public static int ActiveVersion { get; private set; }
// The runtime body MeshCollider (baked skinned mesh) other players' capsules collide with. MeshPainter
// creates it in Start - a frame after OnNetworkSpawn - so resolve it lazily and cache once it exists.
private MeshCollider _bodyCollider;
/// <summary>This avatar's body collider (the paint MeshCollider), or null until it has been created.
/// Cached on first successful resolve.</summary>
public MeshCollider BodyCollider
{
get
{
if (!_bodyCollider) _bodyCollider = GetComponentInChildren<MeshCollider>(true);
return _bodyCollider;
}
}
internal static void CountRoles(out int hunters, out int hiders)
{
hunters = 0;