using Unity.Netcode; using UnityEngine; /// /// Щит: удержание F — поднят (нет стрельбы, иммунитет к пулям, замедление). /// Состояние синхронизируется через NetworkVariable (видно на клонах и у других игроков). /// public class PlayerShield : NetworkBehaviour { [SerializeField] private GameObject shieldVisual; [SerializeField] private float shieldMoveSpeedMultiplier = 0.45f; public NetworkVariable isActive = new NetworkVariable(false); private PlayerHealth playerHealth; private bool inputEnabled; public bool IsShieldUp => isActive.Value; public float MoveSpeedMultiplier => isActive.Value ? shieldMoveSpeedMultiplier : 1f; public override void OnNetworkSpawn() { isActive.OnValueChanged += OnShieldChanged; UpdateVisual(isActive.Value); } public override void OnNetworkDespawn() { isActive.OnValueChanged -= OnShieldChanged; } /// Владелец игрока — читает F и шлёт на сервер. public void InitInput() { inputEnabled = true; playerHealth = GetComponent(); } private void Update() { if (!inputEnabled || !IsOwner) return; if (playerHealth != null && playerHealth.isDead.Value) return; bool _wantShield = Input.GetKey(KeyCode.F); if (_wantShield == isActive.Value) return; SetShieldServerRpc(_wantShield); } /// Сервер: для клонов при воспроизведении записи. public void SetShieldState(bool _active) { if (!IsServer) return; isActive.Value = _active; } [ServerRpc] private void SetShieldServerRpc(bool _active) { if (playerHealth == null) playerHealth = GetComponent(); if (playerHealth != null && playerHealth.isDead.Value) return; isActive.Value = _active; } private void OnShieldChanged(bool _previous, bool _current) => UpdateVisual(_current); private void UpdateVisual(bool _active) { if (shieldVisual != null) shieldVisual.SetActive(_active); } }