Part of these game systems:
beginner Health & Combat

Health System

Reusable health component with damage, healing, invincibility frames, and events.

Unity 2022.3+ · 2.4 KB · HealthSystem.cs

How to Use

1

Attach to any GameObject that needs health (player, enemies, destructibles)

2

Configure max health and invincibility duration

3

Hook up events in the inspector or via code

4

Call TakeDamage() and Heal() from other scripts

Features

  • Damage and healing with clamped health values
  • Invincibility frames with configurable duration after taking damage
  • UnityEvent callbacks for health changed, damaged, healed, and death
  • Public properties for HealthPercent, IsAlive, and IsInvincible checks
  • SetMaxHealth with optional heal-to-full for level-up scenarios
  • ResetHealth method for respawn or checkpoint restoration

When to Use This

Essential for virtually any game with damageable entities — platformers, shooters, RPGs, tower defense, and survival games. Use this on players, enemies, destructible objects, or even bosses. It is the universal building block that other combat scripts (damage popups, health bars, weapon systems) connect to via events.

Common Mistakes

Calling TakeDamage() with a negative value does nothing because the script guards against it — use Heal() instead. If OnDeath doesn't seem to fire, check that invincibilityDuration isn't set too high, preventing subsequent hits from registering. Remember that events set in the Inspector are per-instance, so prefab overrides may not carry your event wiring to spawned copies.

Source Code

HealthSystem.cs
C#
using UnityEngine;
using UnityEngine.Events;

public class HealthSystem : MonoBehaviour
{
    [Header("Health")]
    [SerializeField] private float maxHealth = 100f;
    [SerializeField] private float currentHealth;

    [Header("Invincibility")]
    [SerializeField] private float invincibilityDuration = 0.5f;
    private float invincibilityTimer;

    [Header("Events")]
    public UnityEvent<float, float> OnHealthChanged; // current, max
    public UnityEvent OnDeath;
    public UnityEvent OnDamaged;
    public UnityEvent OnHealed;

    public float CurrentHealth => currentHealth;
    public float MaxHealth => maxHealth;
    public float HealthPercent => currentHealth / maxHealth;
    public bool IsAlive => currentHealth > 0f;
    public bool IsInvincible => invincibilityTimer > 0f;

    private void Awake()
    {
        currentHealth = maxHealth;
    }

    private void Update()
    {
        if (invincibilityTimer > 0f)
            invincibilityTimer -= Time.deltaTime;
    }

    public void TakeDamage(float damage)
    {
        if (!IsAlive || IsInvincible || damage <= 0f) return;

        currentHealth = Mathf.Max(0f, currentHealth - damage);
        invincibilityTimer = invincibilityDuration;

        OnHealthChanged?.Invoke(currentHealth, maxHealth);
        OnDamaged?.Invoke();

        if (!IsAlive)
            OnDeath?.Invoke();
    }

    public void Heal(float amount)
    {
        if (!IsAlive || amount <= 0f) return;

        currentHealth = Mathf.Min(maxHealth, currentHealth + amount);

        OnHealthChanged?.Invoke(currentHealth, maxHealth);
        OnHealed?.Invoke();
    }

    public void SetMaxHealth(float newMax, bool healToFull = false)
    {
        maxHealth = newMax;
        if (healToFull)
            currentHealth = maxHealth;
        else
            currentHealth = Mathf.Min(currentHealth, maxHealth);

        OnHealthChanged?.Invoke(currentHealth, maxHealth);
    }

    public void ResetHealth()
    {
        currentHealth = maxHealth;
        invincibilityTimer = 0f;
        OnHealthChanged?.Invoke(currentHealth, maxHealth);
    }
}