Write a Custom Health Modifier

Write a Custom Health Modifier

๐ŸŽฏ Goal

Change incoming damage, such as armor that halves it.

๐Ÿงฐ What You Need

  • A script that derives from HealthModifier
  • Health on the same GameObject

๐Ÿชœ Steps

Derive from HealthModifier

Create a script that derives from HealthModifier and implement ApplyModifier. It receives the incoming hit and returns the damage to apply instead. Return 0 or less to block the hit.

using UnityEngine;
using GlowingRifts.ModularHealthSystem;

public class Armor : HealthModifier
{
    [Range(0, 1)][SerializeField] private float _reduction = 0.5f;

    public override float ApplyModifier(DamageData damage)
    {
        return damage.damagePoints * (1f - _reduction);
    }
}

Add it next to Health

Add the script to the same GameObject as Health. HealthModifier requires a Health there, finds it on Awake and hooks into it when the component is enabled. Every call to Health.Hurt then asks your modifier first.

Turn it on and off

Enable the component to apply it and disable it to remove it, from an animation, a UnityEvent or code. A disabled modifier unhooks itself and has no effect.

๐Ÿงช Example

Invincibility is the built-in modifier. Its ApplyModifier returns 0, so every hit is blocked while it’s enabled. It also raises its own events from OnEnable and OnDisable, calling the base methods so it still hooks and unhooks:

protected override void OnEnable()
{
    OnInvincibilityStarted.Invoke();
    base.OnEnable();
}

The DamageData also lets a modifier decide by who caused the hit. This one blocks friendly fire:

public class NoFriendlyFire : HealthModifier
{
    public override float ApplyModifier(DamageData damage)
    {
        bool sameTeam = damage.instigator && damage.instigator.CompareTag(tag);
        return sameTeam ? 0f : damage.damagePoints;
    }
}

๐Ÿ’ก Tips

  • Several modifiers can sit on one object. They run in the order they were enabled, and each receives the damage left by the previous one.
  • Only Hurt runs modifiers. Heal and AffectHealth skip them.
  • Return damage.damagePoints unchanged to let a hit through.
  • If you override Awake, OnEnable or OnDisable, call the base method.
  • A modifier can keep its own state, such as a shield that absorbs damage until it runs out. See the Shield example in the scripting reference.

๐Ÿ”— Related