> For the complete documentation index, see [llms.txt](https://morningheartgames.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://morningheartgames.gitbook.io/docs/gameplay-ability-toolkit/build-with-it/04-authoring-effects.md).

# Authoring Effects

> Online doc: <https://morningheartgames.gitbook.io/docs/gameplay-ability-toolkit/foundations/04-authoring-effects?fallback=true>

Effects are reusable gameplay rule assets. They can modify attributes, grant tags, play cues, grant abilities, apply conditional effects, or run custom runtime logic.

Most effects only need an `EffectDefinition`. Create a custom `EffectRuntime` only when the effect needs behavior beyond modifier writes and built-in lifecycle rules.

![Practical effect stacking and overflow lifecycle diagram.](/files/uVGoeG7WQTYC4LBXYwRE)

## Use This Page When

| You want to build...                                  | Start with                                                          |
| ----------------------------------------------------- | ------------------------------------------------------------------- |
| One-shot damage, healing, or resource cost            | An `Instant` effect with attribute modifiers.                       |
| Timed buffs, debuffs, cooldowns, or burn/poison ticks | A `Duration` effect with duration, period, tags, cues, or stacking. |
| Equipment bonuses, auras, toggles, or passives        | An `Infinite` effect that is removed by gameplay logic.             |
| Custom apply/execute/remove behavior                  | A custom `EffectRuntime`, after the asset-only shape is clear.      |

For an independent project, keep the first version observable: one target attribute, one modifier, one cue or log signal, then add stacking, overflow, and conditional effects.

## Editor Entry Points

Create effects from the Dashboard **Effects** page or from the Project window.

```
Tools > Gameplay Ability Toolkit > Dashboard > Effects
```

The Effects page is useful when you want to generate scripts, create an asset from an existing effect type, or confirm that creatable effect types are available.

Project window path:

```
Project window right-click > Create > Gameplay Ability Toolkit > Effect Asset...
```

![Unity Editor screenshot of the Create Effect Asset picker.](/files/QPAaBIx7OYAKEUecjsMf)

Use the picker when you already have a concrete `EffectDefinition` type. Use script generation when you need a new `EffectDefinition` and optional `EffectRuntime` subclass.

## The Three Layers

| Layer      | Type               | Responsibility                                                                   |
| ---------- | ------------------ | -------------------------------------------------------------------------------- |
| Definition | `EffectDefinition` | Type, duration, period, modifiers, stacking, tags, cues, conditional effects.    |
| Runtime    | `EffectRuntime`    | Optional custom apply, execute, activation, deactivation, and removal logic.     |
| Spec       | `EffectSpec`       | Per-application active instance, stack count, remaining time, magnitude context. |

## Creating an Effect

Two Create menu entries are available under `Create > Gameplay Ability Toolkit` and from the **Effects** page in `Tools > Gameplay Ability Toolkit > Dashboard`:

| Entry                | Use it when                                                            |
| -------------------- | ---------------------------------------------------------------------- |
| **Effect Asset...**  | An existing `EffectDefinition` subclass already covers the behavior.   |
| **Effect Script...** | You need a new definition/runtime pair and want boilerplate generated. |

The script creation window validates class names, namespace format, and output folder location.

### Create A Basic Effect Asset

1. In the Project window, select your `Effects/` folder.
2. Right-click and choose `Create > Gameplay Ability Toolkit > Effect Asset...`.
3. Pick `EffectDefinition` or a custom concrete subclass.
4. Click **Create**.
5. Rename the asset with the `GE_` prefix, such as `GE_Damage` or `GE_Burn`.
6. Select the asset and configure the Inspector fields.

If the expected type does not appear, confirm it is concrete, derives from `EffectDefinition`, derives from `ScriptableObject`, and is not compiled into a test assembly.

### First Inspector Pass

Configure effects in this order:

| Step | Inspector area                                                       |
| ---- | -------------------------------------------------------------------- |
| 1    | Set `Type`: `Instant`, `Duration`, or `Infinite`.                    |
| 2    | Set `Duration` and `Period` if the effect remains active.            |
| 3    | Add modifiers and choose target attributes.                          |
| 4    | Choose magnitude source for each modifier.                           |
| 5    | Add granted tags, granted abilities, or cues if needed.              |
| 6    | Configure stacking only after the single-application behavior works. |
| 7    | Add conditional or overflow effects last.                            |

Test one behavior at a time. A duration effect with modifiers, period, stacking, overflow, conditional entries, cues, and granted abilities is possible, but hard to debug if authored all at once.

## Effect Type Matrix

| Type       | Lifetime           | Modifier behavior                                 | Typical use                                           |
| ---------- | ------------------ | ------------------------------------------------- | ----------------------------------------------------- |
| `Instant`  | No active lifetime | Executes once on application.                     | Damage, healing, resource costs, one-shot recovery.   |
| `Duration` | Finite timer       | Aggregates while active or executes periodically. | Time-limited buffs, DoTs, cooldowns, temporary state. |
| `Infinite` | Until removed      | Aggregates while active or executes periodically. | Passives, auras, toggles, equipment grants.           |

`Duration` effects expire automatically. `Infinite` effects must be removed explicitly or by tag-driven removal.

### Choosing A Type

Use this decision path:

```mermaid
flowchart TD
    Once["Should it happen once immediately?"]
    Instant["Use Instant"]
    Timed["Should it expire automatically?"]
    Duration["Use Duration"]
    Infinite["Use Infinite"]

    Once -- "Yes" --> Instant
    Once -- "No" --> Timed
    Timed -- "Yes" --> Duration
    Timed -- "No" --> Infinite
```

Examples:

| Gameplay rule                                      | Effect type |
| -------------------------------------------------- | ----------- |
| Spend 20 Mana                                      | `Instant`   |
| Heal 30 Health                                     | `Instant`   |
| Burn for 5 seconds                                 | `Duration`  |
| Haste for 8 seconds                                | `Duration`  |
| Equipment grants +10 MaxHealth while equipped      | `Infinite`  |
| Aura grants a tag until the aura source is removed | `Infinite`  |

## Modifier Order

All active modifiers for an attribute resolve in a fixed order:

```
CurrentValue = ((BaseValue + AddBase) * MultiplyAdditive / DivideAdditive * MultiplyCompound) + AddFinal
```

`Override` short-circuits the chain. Do not rely on inspector list order to change this formula.

### Authoring Modifiers

For each modifier, verify:

1. The target `AttributeId` points to the intended attribute definition.
2. The operation matches the gameplay rule.
3. The magnitude source can resolve at runtime.
4. Negative values are intentional for damage or costs.
5. Clamping is defined on the attribute if the value should stay inside a range.

Common modifier choices:

| Rule                         | Operation                                                  |
| ---------------------------- | ---------------------------------------------------------- |
| Damage Health                | `Add` with negative magnitude                              |
| Heal Health                  | `Add` with positive magnitude                              |
| Increase max-like base value | Base operation, if your attribute design uses base changes |
| Temporary speed multiplier   | Multiplicative operation on a duration/infinite effect     |
| Force a state value          | `Override`, used sparingly                                 |

## Periodic vs Aggregator-Driven Effects

Duration and infinite effects choose one of two modes:

| Mode              | Configuration | Behavior                                                                                |
| ----------------- | ------------- | --------------------------------------------------------------------------------------- |
| Periodic          | `Period > 0`  | Runs `Execute()` every period. Each tick behaves like an instant application.           |
| Aggregator-driven | `Period == 0` | Modifiers contribute continuously to current attribute values while the spec is active. |

An effect should not be both. Validation warns on invalid combinations such as an instant effect with a period.

## Stacking

Stacking begins with the key policy:

| Policy                | Meaning                                                           |
| --------------------- | ----------------------------------------------------------------- |
| `IndependentInstance` | Each application creates a separate active spec.                  |
| `ByDefinition`        | Applications of the same definition stack together on the target. |
| `BySource`            | Applications stack per definition and source GameObject.          |

Important stack settings:

| Setting                              | Meaning                                                         |
| ------------------------------------ | --------------------------------------------------------------- |
| `MaxStack`                           | Maximum stack count.                                            |
| `RefreshOnSuccessfulApplication`     | Reapplying resets duration.                                     |
| `ResetPeriodOnSuccessfulApplication` | Reapplying resets the period clock.                             |
| `ClearStackOnOverflow`               | At cap, overflow clears the existing stack.                     |
| `DenyOverflowApplication`            | At cap, reject the new application after overflow effects fire. |
| `OverflowEffects`                    | Effects applied when a stack would exceed the cap.              |

```mermaid
flowchart LR
    Apply["Apply effect"]
    Key["Find stack by policy"]
    Cap["At max stack?"]
    Inc["Increase or refresh stack"]
    Overflow["Apply overflow effects"]
    Deny["Deny or clear based on policy"]

    Apply --> Key --> Cap
    Cap -- "No" --> Inc
    Cap -- "Yes" --> Overflow --> Deny
```

### Stacking Authoring Ability

1. Make the effect work with one application first.
2. Set a stacking key policy.
3. Set `MaxStack`.
4. Enable duration or period refresh only if repeated applications should reset timers.
5. Add overflow effects only after stack count behavior is correct.
6. Subscribe to `EventEffectStackChanged` in UI if the player needs stack feedback.

When debugging stacks, watch for three separate questions: did the effect apply, did it merge with an existing spec, and did stack count change?

## Conditional Effects

`ConditionalEffectEntry` lets an effect apply additional effects only when the target matches a tag query at apply time.

Common uses:

* Fire impact applies bonus damage only to targets already carrying `Effect.Burn`.
* A heal applies a cleanse only to targets carrying a debuff tag.
* A weapon effect applies a stagger only to enemies without `State.Armored`.

Conditional entries can be nested, but keep chains readable. If a chain becomes hard to inspect, move the rule into a custom runtime or calculation.

### Conditional Authoring Ability

1. Create the parent effect.
2. Create the child effect that should conditionally apply.
3. Add a conditional entry to the parent.
4. Configure the tag query on the entry.
5. Apply the parent to a target without the required tag and verify the child does not apply.
6. Apply the parent to a target with the required tag and verify the child applies.

Use clear tags such as `Effect.Burn`, `State.Guarding`, or `State.Frozen` so the condition reads like a design rule.

## Inhibition

`InhibitionTags` and `InhibitionQuery` suspend an active effect's modifier writes without removing the spec.

Use inhibition when the effect should remain present but temporarily stop contributing:

* Regeneration suppressed while `State.Stealthed`.
* Aura disabled while `State.Silenced`.
* Passive bonus paused during a scripted state.

While inhibited, granted tags and granted abilities remain applied, and the period clock keeps advancing.

## Granted Tags, Abilities, and Cues

| Feature            | Behavior                                                           |
| ------------------ | ------------------------------------------------------------------ |
| `GrantedTags`      | Added to the target while the effect is active.                    |
| `GrantedAbilities` | Granted while the effect is active, removed when the effect ends.  |
| Gameplay cues      | Trigger decoupled visual/audio/gameplay feedback through cue tags. |

This is how a single duration effect can both modify attributes and mark the actor as being in a state such as guarding, burning, invulnerable, or empowered.

## Magnitude Sources

| Source            | Use it when                                                 |
| ----------------- | ----------------------------------------------------------- |
| `LevelBased`      | A constant, coefficient, or curve based on level is enough. |
| `AttributeBased`  | The value depends on source or target attributes.           |
| `SetByCaller`     | Runtime code supplies the value during application.         |
| Custom calculator | A reusable formula needs custom C# logic.                   |

Custom calculators are covered in [Extending the Framework](/docs/gameplay-ability-toolkit/build-with-it/05-extending.md).

## Custom EffectRuntime

Use a runtime subclass for side effects and custom preconditions:

```csharp
using GameplayAbilityToolkit.Core;
using UnityEngine;

public sealed class BurnEffectDefinition : EffectDefinition
{
    public override EffectRuntime CreateRuntime() => new BurnEffectRuntime();
}

public sealed class BurnEffectRuntime : EffectRuntime
{
    public override void OnApplied(EffectSpec spec)
    {
        // Spawn or start feedback.
    }

    public override void OnExecuted(EffectSpec spec)
    {
        // Run per-tick behavior.
    }

    public override void OnRemoved(EffectSpec spec)
    {
        // Stop feedback or release runtime resources.
    }

    public override bool CanApply(GameObject target, int level)
    {
        return base.CanApply(target, level) && !target.CompareTag("FireImmune");
    }
}
```

The `EffectRuntime` hooks are past-tense notifications because the framework has already performed the underlying lifecycle mutation.

## Author-Time Validation

`EffectDefinition.OnValidate` warns about common invalid setups, including:

* Empty modifier lists for non-calculation effects.
* `Instant` effects with a positive period.

Warnings appear in the Console with the asset as context, so the effect is one click away.

## Editor Debugging Checklist

When an effect does not behave as expected:

1. Confirm the effect asset is the one actually referenced by the ability or script.
2. Confirm the target actor has the target attribute.
3. Confirm the application request target and instigator are correct.
4. Confirm tag requirements or conditions are satisfied.
5. For duration/infinite effects, inspect the active effect list at runtime.
6. For stacking, watch stack count events instead of only watching attribute values.
7. For cues, confirm the cue tag is registered in the active `GameplayCueLibrary`.

## Next Steps

* Read [Authoring Abilities](/docs/gameplay-ability-toolkit/build-with-it/03-authoring-abilities.md) to activate effects from player, AI, input, or gameplay events.
* Read [Cookbook](/docs/gameplay-ability-toolkit/build-with-it/07-cookbook.md) for DoTs, cooldown HUD, armor mitigation, ground AoE, channeling, and save/load recipes.
* Open the [Basic Tutorial](/docs/gameplay-ability-toolkit/try-it/basictutorial.md) to inspect concrete `GE_*` assets.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://morningheartgames.gitbook.io/docs/gameplay-ability-toolkit/build-with-it/04-authoring-effects.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
