Netcode: receiver-side paint reveal gate + fur pipette gating
Hide remote avatars until this client has actually applied a snapshot reaching the owner-published baseline cutoff, preventing the default grey/white material from flashing before a player's painting has loaded. - PlayerPaintSync: owner-authoritative _publishedCutoff NetworkVariable, receiver tracks _appliedCutoff; explicit blank publish for never-painted avatars so they still reveal. - NetworkPlayerSetup: cache _paintSync, hide body renderers on spawn, gate UpdateVisibility on PaintRevealReady. - MeshPainter.Pick: fur toggle now follows pickedHeight (own paint-mesh only), matching the Occlusion/Height pipette behaviour. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
49704448e9
commit
ed09d6a1b0
3 files changed
+47
-6
No files matched your search
@@ -108,6 +108,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
private float _renderGateUntil; // Time.time deadline that lifts _renderGate; frame-driven (see UpdateVisibility) so a mid-settle disable/despawn can't strand the body hidden forever
|
||||
|
||||
private MeshPainter _painter; // owns the per-avatar material instance carrying _XRayColor
|
||||
private PlayerPaintSync _paintSync; // receiver-side reveal gate: body hidden until this client applied the painting
|
||||
private ConcealmentMeter _concealment; // owner-only embedded-percent source (disabled on remotes)
|
||||
private PlayerCharacterController _controller; // sibling, cached (the freeze re-asserts per frame)
|
||||
private bool _xrayApplied;
|
||||
@@ -120,6 +121,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
_active.Add(this); // scoreboard registry (paired with OnNetworkDespawn)
|
||||
_bodyRenderers = GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
||||
_painter = GetComponentInChildren<MeshPainter>(true);
|
||||
_paintSync = GetComponentInChildren<PlayerPaintSync>(true);
|
||||
_concealment = GetComponentInChildren<ConcealmentMeter>(true);
|
||||
_isFound.OnValueChanged += OnFoundChanged;
|
||||
if (_isFound.Value) ApplyFound(); // defensive: an avatar is never normally spawned already-found
|
||||
@@ -150,6 +152,11 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
// simulation (input/movement) and the CharacterController's own depenetration.
|
||||
DisableLocalSimulation();
|
||||
|
||||
// Receiver-side reveal gate: hide the body from the very first frame until this client has applied
|
||||
// the owner's painting baseline (see PlayerPaintSync.PaintRevealReady). Without this a freshly
|
||||
// spawned remote flashes the default grey/white material before its painting arrives.
|
||||
SetBodyRenderers(false);
|
||||
|
||||
// The concealment meter (per-frame bake + voxelization + overlap) only feeds the LOCAL player;
|
||||
// a remote's concealment is computed on its own owner's machine, so here it is wasted CPU.
|
||||
if (_concealment) _concealment.enabled = false;
|
||||
@@ -274,7 +281,10 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
if (IsOwner && !found) return;
|
||||
|
||||
// While the conversion render gate is up, the body stays hidden no matter what ComputeVisible says.
|
||||
bool visible = !_renderGate && ComputeVisible(found);
|
||||
// The paint gate is an additional hard hide: a remote body never shows before this client has
|
||||
// applied its painting (owner is always ready; a null sync - offline/single-player - never gates).
|
||||
bool paintReady = !_paintSync || _paintSync.PaintRevealReady;
|
||||
bool visible = paintReady && !_renderGate && ComputeVisible(found);
|
||||
if (_visibilityApplied && visible == _lastVisible) return;
|
||||
SetBodyRenderers(visible);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user