142 lines
4.7 KiB
C#
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);
|
|
}
|
|
}
|