Files
Learning-UnityNGO/Assets/CONTENT/FEATURES/DEV-TEST/Scripts/PlayerFacade.cs
T
2026-07-06 18:01:21 +03:00

142 lines
4.7 KiB
C#

using UnityEngine;
using Unity.Netcode;
using System.Collections;
public class PlayerFacade : NetworkBehaviour
{
private const string OwnerHiddenBodyLayerName = "OwnerHiddenBody";
[SerializeField] private PlayerMovement playerMovement;
[SerializeField] private PlayerHealth playerHealth;
[SerializeField] private PlayerShoot playerShoot;
[SerializeField] private PlayerShield playerShield;
[SerializeField] private PlayerUIController playerUIController;
[Header("First / third person setup")]
[SerializeField] private Transform thirdPersonVisualRoot;
[SerializeField] private Camera playerCamera;
[SerializeField] private Camera playerHandCamera;
[SerializeField] private GameObject fpvHands;
[SerializeField] private GameObject tpvHands;
public PlayerHealth PlayerHealth => playerHealth;
private void Awake()
{
if (thirdPersonVisualRoot == null)
thirdPersonVisualRoot = transform.Find("Root");
Transform _cameraRoot = transform.Find("Camera");
if (playerCamera == null && _cameraRoot != null)
playerCamera = _cameraRoot.GetComponent<Camera>();
if (playerHandCamera == null && _cameraRoot != null)
playerHandCamera = _cameraRoot.Find("Camera-Hands")?.GetComponent<Camera>();
if (fpvHands == null && _cameraRoot != null)
fpvHands = _cameraRoot.Find("FPV-Hands")?.gameObject;
if (tpvHands == null)
tpvHands = transform.Find("TPV-Hands")?.gameObject;
}
public override void OnNetworkSpawn()
{
// Клон (GhostPlayer) — серверный объект. На хосте он считается IsOwner,
// из-за чего перехватывал HUD игрока. Игроковую логику на клоне не запускаем.
if (GetComponent<GhostPlayer>() != null) return;
SetupCamerasAndHands();
if (IsOwner)
HideOwnThirdPersonVisual();
if (IsOwner)
{
StartCoroutine(InitPlayerUIController());
if (playerMovement != null)
playerMovement.Init();
if (playerShoot != null)
playerShoot.Init();
if (playerShield != null)
playerShield.InitInput();
}
if (playerHealth != null)
playerHealth.Init(IsServer);
}
private void SetupCamerasAndHands()
{
if (playerCamera != null)
{
playerCamera.enabled = IsOwner;
AudioListener _listener = playerCamera.GetComponent<AudioListener>();
if (_listener != null)
_listener.enabled = IsOwner;
}
if (playerHandCamera != null)
playerHandCamera.enabled = IsOwner;
if (fpvHands != null)
fpvHands.SetActive(IsOwner);
if (tpvHands != null)
tpvHands.SetActive(!IsOwner);
if (!IsOwner)
return;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
int _hiddenLayer = LayerMask.NameToLayer(OwnerHiddenBodyLayerName);
if (playerCamera != null && _hiddenLayer >= 0)
playerCamera.cullingMask &= ~(1 << _hiddenLayer);
}
// Свой Root у владельца переводим на слой, который его FPV-камера не рисует.
// На других клиентах Root остаётся как в префабе — чужие тела видны.
// Слой меняется только локально у владельца, в сеть не уходит.
private void HideOwnThirdPersonVisual()
{
if (thirdPersonVisualRoot == null)
return;
int _hiddenLayer = LayerMask.NameToLayer(OwnerHiddenBodyLayerName);
if (_hiddenLayer < 0)
{
Debug.LogWarning($"Layer '{OwnerHiddenBodyLayerName}' is missing. Create it in Tags & Layers.");
return;
}
GameObject _shieldVisual = playerShield != null ? playerShield.ShieldVisual : null;
foreach (Transform _child in thirdPersonVisualRoot.GetComponentsInChildren<Transform>(true))
{
if (_shieldVisual != null &&
(_child.gameObject == _shieldVisual || _child.IsChildOf(_shieldVisual.transform)))
continue;
_child.gameObject.layer = _hiddenLayer;
}
}
private IEnumerator InitPlayerUIController()
{
yield return new WaitUntil(() =>
{
playerUIController = FindFirstObjectByType<PlayerUIController>();
return playerUIController != null;
});
if (playerUIController != null)
playerUIController.Init(this);
}
}