(Feat) Add Network Body
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
using FishNet.Object;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ashwild.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Splits the player's visible body by viewpoint. The local owner's third-person body is
|
||||
/// moved onto a dedicated "local body" layer that his own first-person camera excludes from
|
||||
/// its culling mask, so he never sees his own torso/head clip through the view — while every
|
||||
/// remote client still renders that same body normally. The layer change is purely local and
|
||||
/// never travels over the network, so hiding your body from yourself does not hide it from
|
||||
/// anyone else. The Animator/NetworkAnimator are left untouched, so the third-person animation
|
||||
/// keeps replicating to other players even while the mesh is culled from the owner's own view.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class PlayerBodyVisibility : NetworkBehaviour
|
||||
{
|
||||
#region Serialized Fields
|
||||
|
||||
[Header("Body")]
|
||||
[Tooltip("Root of the third-person body mesh hierarchy (skinned mesh + bones).")]
|
||||
[SerializeField] private GameObject bodyRoot;
|
||||
|
||||
[Header("Local hiding")]
|
||||
[Tooltip("Layer the owner's own body is moved to. The first-person camera must exclude this layer from its culling mask.")]
|
||||
[SerializeField] private string localBodyLayer = "LocalBody";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Network Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// Once ownership is resolved, relayers the third-person body so the owning player's own
|
||||
/// camera stops rendering it. Remote copies return early and keep the body on its authored
|
||||
/// (visible) layer, which is why other players still see it.
|
||||
/// </summary>
|
||||
public override void OnStartClient()
|
||||
{
|
||||
base.OnStartClient();
|
||||
|
||||
if (!base.IsOwner) return;
|
||||
|
||||
if (bodyRoot == null)
|
||||
{
|
||||
Debug.LogError($"[PlayerBodyVisibility] '{name}' has no bodyRoot assigned — cannot hide the local body.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
int layer = LayerMask.NameToLayer(localBodyLayer);
|
||||
if (layer < 0)
|
||||
{
|
||||
Debug.LogError($"[PlayerBodyVisibility] '{name}' — layer '{localBodyLayer}' does not exist. Add it in Project Settings ▸ Tags and Layers, then exclude it from the first-person camera's culling mask.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
SetLayerRecursively(bodyRoot, layer);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Applies a layer to a GameObject and every descendant, since a skinned body spans many
|
||||
/// child renderers and bones that must all move together for the camera cull to hide it fully.
|
||||
/// </summary>
|
||||
private static void SetLayerRecursively(GameObject root, int layer)
|
||||
{
|
||||
root.layer = layer;
|
||||
foreach (Transform child in root.transform)
|
||||
SetLayerRecursively(child.gameObject, layer);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user