Skip to content

🛡️ Health — Shields

Shields intercept incoming damage before it reaches health.

They are opt-in, modular components that plug into HealthSystem and participate in the damage pipeline after PRE rules and before health mutation.

All gameplay shields implement IShield.
Many also implement IShieldPreview to support accurate damage previews.


📦 What Shields Are (and Aren’t)

Shields are - Damage interception layers - Victim-side protection systems - Fully compatible with rules, authority, DOT/HOT, and previews

Shields are not - Rules (they do not run in PRE / POST phases) - Health owners - UI-only aggregates (see ShieldPool for aggregation utilities) - Networking systems

Health works without shields — add them only where needed.


🧩 Built-in Shield Types

CapacityShield

A capacity-based shield pool that absorbs damage until depleted.

Behaviour - Absorbs damage up to current capacity - Breaks when capacity reaches zero - Optional flat and percent reduction applied before capacity consumption

Events - ShieldDamaged(int absorbed) - ShieldBroken() - UnityEvent equivalents for designer hooks

Preview - Implements IShieldPreview - Accurately previews flat/percent reduction and remaining capacity

Typical Uses - Energy shields - Barrier spells - Temporary protection buffs


RechargeableShield

A capacity-based shield that regenerates over time.

Behaviour - Any call to absorption refreshes the regen cooldown - Regenerates via accumulated per-second ticks (frame-rate independent) - Capacity-based absorption identical to CapacityShield

Fields - maxCapacity - regenDelay - regenPerSecond

Events - ShieldDamaged(int absorbed) - ShieldBroken()

Preview - Implements IShieldPreview (capacity-only preview)

Typical Uses - Sci‑fi shields - Rechargeable barriers - Regenerating armour layers


ReductionShield

A stateless mitigation shield.

Behaviour - Applies flat and percent reduction to every hit - Never breaks - No internal capacity

Events - None (pure reduction)

Preview - Implements IShieldPreview (returns remainder after reduction)

Typical Uses - Armour plates - Passive resistances - Environmental mitigation


OverhealShield

A temporary HP pool that decays over time.

Behaviour - Soaks damage before real health - Decays gradually over time - Decay pauses briefly after damage or when temp HP is added - Decay behaviour and max temp can be adjusted at runtime via supported configuration seams

Configuration - SetMaxTemp(int value, bool clampCurrent = true) - ConfigureDecay(float perSecond, float delayAfterHit) - SetUseUnscaledTime(bool value) (optional)

Inspector values define defaults; runtime calls may override them.

Events - ShieldDamaged(int used) - ShieldBroken()

Preview - Implements IShieldPreview

Typical Uses - Overheal mechanics - Temporary buffs - RPG-style bonus HP


ShieldChain

Aggregator that runs multiple shields in sequence.

Behaviour - Executes shields in component (Inspector) order - Passes remaining damage to the next shield - Stops once damage is exhausted - Can optionally skip disabled shield components

Preview - Implements IShieldPreview - Uses per-shield previews where available

Typical Uses - Layered defences - Hybrid setups (reduction + capacity + overheal) - Composite boss shields


ShieldPool (Not an IShield)

A ticket-based shield value accumulator.

Important - Does not implement IShield - HealthSystem will never route damage through it

Purpose - Aggregation of shield values from many sources - UI display - Gameplay systems that need a combined total

Use instead - CapacityShield, RechargeableShield, or OverhealShield for real absorption


🔄 Shield Execution Order

Within the damage pipeline:

PRE Damage Rules
→ Shields (IShield / ShieldChain)
→ HealthSystem.ApplyDamage
→ POST Damage Rules

If a shield fully absorbs damage: - Health takes 0 - POST rules still execute with FinalApplied = 0


🧮 Preview Support

IShieldPreview enables non-mutating damage estimates.

Used by: - HealthSystem.PreviewDamage(...) - AI heuristics - UI preview widgets

If a shield does not implement IShieldPreview: - Preview assumes no absorption - Live gameplay absorption still works - UI/AI estimates may be pessimistic

Best practice:
Always implement IShieldPreview for gameplay shields.


🧠 Custom Shields

You can implement custom shields easily:

public class MyShield : MonoBehaviour, IShield, IShieldPreview
{
    public bool TryAbsorb(ref int damage)
    {
        // mutate damage
        return damage <= 0;
    }

    public int PreviewRemainder(int incoming)
    {
        // non-mutating preview
        return incoming;
    }
}

Tips - Clamp inspector fields in OnValidate() - Keep shields deterministic and side-effect free where possible - Combine with ShieldChain for complex behaviour


❌ What Shields Should Not Do

  • Do not modify health directly
  • Do not implement gameplay rules
  • Do not assume authority or networking
  • Do not replace rule pipelines
  • Do not encode UI logic

Shields exist to intercept damage — nothing else.


🔗 See Also