80 lines
2.1 KiB
C#
80 lines
2.1 KiB
C#
using System;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
[DisallowMultipleComponent]
|
|
[RequireComponent(typeof(NetworkObject))]
|
|
public sealed class NetworkBaseHealth : NetworkBehaviour
|
|
{
|
|
[SerializeField, Min(1)] private int maximumHealth = 10;
|
|
[SerializeField] private UnityEvent<int> healthChanged;
|
|
[SerializeField] private UnityEvent depleted;
|
|
|
|
private readonly NetworkVariable<int> currentHealth = new(
|
|
0,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server);
|
|
|
|
public int MaximumHealth => Mathf.Max(1, maximumHealth);
|
|
public int CurrentHealth => currentHealth.Value;
|
|
public bool IsDepleted => CurrentHealth <= 0;
|
|
|
|
public event Action<int> Changed;
|
|
public event Action Depleted;
|
|
|
|
private void OnValidate() => maximumHealth = Mathf.Max(1, maximumHealth);
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
currentHealth.OnValueChanged += HandleHealthChanged;
|
|
|
|
if (IsServer)
|
|
currentHealth.Value = MaximumHealth;
|
|
|
|
ApplyState(currentHealth.Value, false);
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
currentHealth.OnValueChanged -= HandleHealthChanged;
|
|
}
|
|
|
|
public bool ApplyDamage(int amount)
|
|
{
|
|
if (!IsServer || !IsSpawned || amount <= 0 || IsDepleted)
|
|
return false;
|
|
|
|
currentHealth.Value = Mathf.Max(0, CurrentHealth - amount);
|
|
return true;
|
|
}
|
|
|
|
public void ResetHealth()
|
|
{
|
|
if (IsServer && IsSpawned)
|
|
currentHealth.Value = MaximumHealth;
|
|
}
|
|
|
|
[ContextMenu("Debug/Apply One Damage (Server Play Mode)")]
|
|
private void ApplyDebugDamage()
|
|
{
|
|
if (Application.isPlaying)
|
|
ApplyDamage(1);
|
|
}
|
|
|
|
private void HandleHealthChanged(int previous, int current) =>
|
|
ApplyState(current, previous > 0 && current <= 0);
|
|
|
|
private void ApplyState(int health, bool becameDepleted)
|
|
{
|
|
Changed?.Invoke(health);
|
|
healthChanged?.Invoke(health);
|
|
|
|
if (!becameDepleted)
|
|
return;
|
|
|
|
Depleted?.Invoke();
|
|
depleted?.Invoke();
|
|
}
|
|
}
|