Replicate the composed wall-lean/ground-raise/ceiling-lean mesh offset (meshOffsetTarget.localPosition) as an owner-authoritative NetworkVariable so remote avatars lean and raise instead of staying rigid; remote eases it onto the visual root. Disable ConcealmentMeter on remotes (its per-frame skinned bake, voxelization and physics overlaps only feed the local player). SkinnedColliderBaker stays active on remotes because the paint replay rasterizes its live BakedMesh for UV mapping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
44 lines
2.1 KiB
C#
44 lines
2.1 KiB
C#
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 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]
|
|
public class NetworkPlayerSetup : NetworkBehaviour
|
|
{
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
var controller = GetComponent<PlayerCharacterController>();
|
|
|
|
if (IsOwner)
|
|
{
|
|
var manager = FindFirstObjectByType<GameModeManager>(FindObjectsInactive.Include);
|
|
if (manager)
|
|
manager.BindLocalPlayer(controller);
|
|
return;
|
|
}
|
|
|
|
// Remote avatar: NetworkTransform owns the transform here, so disable the local
|
|
// simulation (input/movement) and the CharacterController's own depenetration.
|
|
if (controller) controller.enabled = false;
|
|
var cc = GetComponent<CharacterController>();
|
|
if (cc) cc.enabled = false;
|
|
|
|
// Owner cleanup: the concealment meter is a per-frame skinned-mesh bake + voxelization +
|
|
// physics overlap whose result only feeds the LOCAL player (HUD / gameplay). A remote avatar's
|
|
// concealment is computed on its own owner's machine, so running it here is pure wasted CPU.
|
|
var concealment = GetComponentInChildren<ConcealmentMeter>(true);
|
|
if (concealment) concealment.enabled = false;
|
|
|
|
// NOTE: SkinnedColliderBaker deliberately stays ENABLED on remotes. MeshPainter's stamp replay
|
|
// (ApplyNetworkStamp -> DrawBrushGpu) rasterizes the baker's live, per-frame BakedMesh to map a
|
|
// 3D brush placement into UV space; freezing the bake would mis-map replicated paint onto any
|
|
// non-rest pose. Its bake is the necessary cost of correct remote paint, not wasted work.
|
|
}
|
|
}
|