File size: 2,342 Bytes
40c0886
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
using UnityEngine;
using UnityEngine.Events;

namespace UnityAgent
{
    /// <summary>
    /// Damageable entity with health regen and death event. Pairs with the
    /// optional <see cref="HealthBar"/> UI component.
    /// </summary>
    public class HealthSystem : MonoBehaviour
    {
        [Header("Health")]
        public float maxHealth = 100f;
        public float currentHealth { get; private set; }
        public float regenPerSecond = 1f;
        public float regenDelay = 5f;

        [Header("Events")]
        public UnityEvent onDeath;
        public UnityEvent<float> onDamaged;

        private float _lastDamageTime;
        private bool _dead;

        public float Normalised => currentHealth / maxHealth;

        private void Awake()
        {
            currentHealth = maxHealth;
        }

        private void Update()
        {
            if (_dead) return;
            if (Time.time - _lastDamageTime > regenDelay && currentHealth < maxHealth)
            {
                currentHealth = Mathf.Min(maxHealth, currentHealth + regenPerSecond * Time.deltaTime);
            }
        }

        public void TakeDamage(float amount)
        {
            if (_dead) return;
            currentHealth = Mathf.Max(0f, currentHealth - amount);
            _lastDamageTime = Time.time;
            onDamaged?.Invoke(amount);
            if (currentHealth <= 0f) Die();
        }

        public void Heal(float amount)
        {
            if (_dead) return;
            currentHealth = Mathf.Min(maxHealth, currentHealth + amount);
        }

        private void Die()
        {
            _dead = true;
            onDeath?.Invoke();
            Destroy(gameObject, 0.5f);
        }
    }

    /// <summary>
    /// Simple health bar that reads a <see cref="HealthSystem"/> and updates
    /// a child <c>Image.fillAmount</c>.
    /// </summary>
    public class HealthBar : MonoBehaviour
    {
        public HealthSystem source;
        public UnityEngine.UI.Image fillImage;
        public bool hideWhenFull = true;

        private void Update()
        {
            if (source == null || fillImage == null) return;
            float n = source.Normalised;
            fillImage.fillAmount = n;
            if (hideWhenFull) fillImage.transform.parent.gameObject.SetActive(n < 0.999f);
        }
    }
}