> 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/02-architecture.md).

# Architecture

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

Gameplay Ability Toolkit uses a practical split that helps small teams keep gameplay rules reusable: author gameplay as data, then execute that data through runtime objects owned by an actor.

The Unity version expresses the model through `MonoBehaviour` actors and `ScriptableObject` definitions.

For subsystem-level details, use the [Subsystem Guide](/docs/gameplay-ability-toolkit/subsystems/subsystems.md). Architecture stays high-level; each subsystem page covers exact configuration and debugging steps.

## What To Learn First

| If you are...               | Focus on                                                                               | You can postpone                                                       |
| --------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Evaluating the toolkit      | `AbilitySystemComponent`, project-level assets, and the Definition/Spec/Runtime split. | Scheduler internals, custom drivers, and extension registration.       |
| Building your first ability | Definitions, specs, runtime objects, tags, costs, cooldowns, and effect application.   | Custom magnitude calculators, save/load, and performance test details. |
| Extending the framework     | Public subsystem entry points and explicit extension interfaces.                       | Internal editor drawers, generated files, and test helpers.            |

Independent developers usually get the most value by keeping gameplay rules in assets first, then adding code only where the built-in authoring surface is not enough.

## Definition, Spec, Runtime

| Layer          | Lives in                 | Holds                                                 | Edited by                                 |
| -------------- | ------------------------ | ----------------------------------------------------- | ----------------------------------------- |
| **Definition** | `ScriptableObject` asset | Shared configuration data                             | Designers and developers in the Inspector |
| **Spec**       | Plain C# object          | Per-grant or per-application metadata                 | The framework                             |
| **Runtime**    | Plain C# object          | Execution logic and per-actor or per-activation state | Created automatically                     |

This split keeps assets reusable and runtime state isolated. One `EffectDefinition` can be shared by every enemy in a scene; each application receives its own `EffectSpec`.

## AbilitySystemComponent

`AbilitySystemComponent` (ASC) is the MonoBehaviour entry point. It is intentionally a coordinator, not a large rules object.

![Practical AbilitySystemComponent orchestration diagram.](/files/PpRpOKfcMEtuPIly6kvX)

```mermaid
flowchart TB
    ASC["AbilitySystemComponent"]
    Tags["RuntimeTags"]
    Attr["RuntimeAttributes"]
    Effects["RuntimeEffects"]
    Abilities["RuntimeAbilities"]
    Input["AbilityInputQueue"]

    ASC --> Tags
    ASC --> Attr
    ASC --> Effects
    ASC --> Abilities
    ASC --> Input
```

The ASC exposes:

* High-traffic attribute reads such as `TryGetAttributeBaseValue`, `TryGetAttributeCurrentValue`, and `HasAttribute`.
* Aggregate change events for UI and editor surfaces: tags, abilities, effects, attributes, inputs, and activation failures.
* Typed convenience events that bubble up from subsystems: ability activated/ended, effect removed, and effect stack changed.

Game code should usually mutate state through the runtime subsystems rather than treating the ASC as a monolithic service.

### Inspect An ASC In The Editor

1. Select an actor GameObject.
2. Find `AbilitySystemComponent` in the Inspector.
3. Check initial attribute sets, initial effects, granted abilities, and input bindings.
4. Enter Play Mode.
5. Watch runtime debug sections and scene HUD/debug panels if the sample scene provides them.

The ASC Inspector is where you confirm what the actor starts with. The Dashboard is where you confirm the project-level libraries that the actor depends on.

### Project-Level Assets vs Actor-Level Assets

| Asset level      | Examples                                                                            | Where to inspect                                       |
| ---------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Project-level    | `GASConfiguration`, `GameplayTagAsset`, `GameplayCueLibrary`, `AbilityInputLibrary` | `Tools > Gameplay Ability Toolkit > Dashboard > Setup` |
| Actor-level      | `AttributeSet`, granted abilities, initial effects, input binding set               | Actor Inspector                                        |
| Definition-level | `AbilityDefinition`, `EffectDefinition`, `AttributeSetDefinition`                   | Project window asset Inspector                         |
| Runtime-only     | Specs, active tags, active effects, current values                                  | Play Mode debug surfaces, events, or custom UI         |

Do not confuse a definition asset with runtime state. Editing a `GE_Burn` asset changes the rule; applying it in Play Mode creates active `EffectSpec` state on one actor.

## Runtime Lifecycle

```mermaid
flowchart TD
    Awake["ASC Awake / OnEnable"]
    Init["EnsureInitialized"]
    Subsystems["Create runtime subsystems"]
    Initial["Apply initial effects and attributes"]
    Register["Register with AbilitySystemScheduler"]
    Update["Scheduler Update: input, abilities, effects"]
    Late["Scheduler LateUpdate: dirty attribute recalculation"]
    Disable["ASC OnDisable: unregister and unsubscribe"]
    Destroy["ASC OnDestroy: cleanup cues, collectors, and subsystems"]

    Awake --> Init --> Subsystems --> Initial --> Register --> Update --> Late
    Late --> Update
    Update --> Disable --> Destroy
```

A hidden `AbilitySystemScheduler` ticks registered ASCs. It is reentrancy-safe, survives domain reload through `RuntimeInitializeOnLoadMethod`, and is `DontDestroyOnLoad` in play mode.

### Why The Scheduler Exists

The scheduler centralizes updates so every ASC follows the same order:

1. Input work is processed.
2. Active abilities tick.
3. Active effects tick.
4. Dirty attributes recalculate in late update.
5. Events reach HUD/debug consumers after state changes.

This keeps input, ability tasks, periodic effects, and attribute recalculation from racing each other.

## Attribute Modifier Order

When `RuntimeAttributes.RecalculateAllDirty` runs, active modifiers collapse into a single current value per attribute:

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

`Override` short-circuits the chain. This order is fixed and should be treated as part of the toolkit contract.

### Reading Attribute Changes

Use these reads when building UI:

| Read                          | Use                                            |
| ----------------------------- | ---------------------------------------------- |
| `TryGetAttributeBaseValue`    | Persistent authored/base value.                |
| `TryGetAttributeCurrentValue` | Final value after active modifiers and clamps. |
| `HasAttribute`                | Guard UI or logic before reading.              |

Most HUDs should display current value. Save systems usually snapshot base values and active effects separately.

## Magnitude Strategies

Each modifier uses a `ModifierMagnitude` strategy:

| Strategy         | Use it when                                                        |
| ---------------- | ------------------------------------------------------------------ |
| `LevelBased`     | The value comes from ability/effect level, a constant, or a curve. |
| `AttributeBased` | The value derives from a captured source or target attribute.      |
| `SetByCaller`    | The value is only known at runtime and is supplied in context.     |

Custom strategies register through `ModifierMagnitudeCalculatorFactory.RegisterCalculatorCreator()`. See [Extending the Framework](/docs/gameplay-ability-toolkit/build-with-it/05-extending.md).

## Attribute Update Pipeline

`RuntimeAttributes` separates planning, calculation, and application:

```mermaid
flowchart LR
    Dirty["Dirty attribute IDs"]
    Calc["Modifier aggregation"]
    Clamp["Clamp and definition hooks"]
    ActorHooks["IAttributeChangeHook"]
    Commit["Commit value and fire events"]

    Dirty --> Calc --> Clamp --> ActorHooks --> Commit
```

Use `RuntimeAttribute` subclasses for definition-level clamp behavior. Use `IAttributeChangeHook` for actor-level reactions such as armor, shields, equipment, stance, or component-driven redirects.

## Tags

`GameplayTag` is a value type with a hashed name. `RuntimeTagCache` precomputes parent hashes so hierarchical matching can answer without allocation.

Each actor has two tag count containers:

| Container            | Meaning                                                                       |
| -------------------- | ----------------------------------------------------------------------------- |
| `OwnedTags`          | State the actor currently has, such as `State.Invulnerable` or `Effect.Burn`. |
| `BlockedAbilityTags` | Ability tags that cannot activate while the count is nonzero.                 |

Count semantics matter. If two active effects grant `Effect.Burn`, removing one decrements the tag count instead of blindly removing the tag.

## Performance Posture

The core runtime targets roughly 500-1000 active ASC actors in production gameplay. Hot paths are designed to be allocation-free:

* Ability activation, effect application, input dispatch, trigger routing, and ticking avoid per-frame allocations.
* Iteration reuses scratch lists and defers mutations during iteration.
* Logging compiles out unless `GAS_LOGGING_ENABLED` is defined.

UI, editor, and debug surfaces are allowed to allocate because they are lower-frequency consumers.

## Editor and Dependency Bootstrap

The editor surface is split so a fresh import can recover from missing dependencies:

* `GameplayAbilityToolkit.DependencyBootstrap.Editor` compiles before Core and cannot reference Core or optional runtime assemblies.
* Core editor assemblies live behind bootstrap-managed define symbols.

Important defines:

| Define                         | Purpose                                                                        |
| ------------------------------ | ------------------------------------------------------------------------------ |
| `GAS_HAS_UNITASK`              | Enables Core and all assemblies that reference Core after UniTask is detected. |
| `GAS_ENABLE_TESTS`             | Enables test assemblies when Unity Test Framework is installed.                |
| `GAS_ENABLE_PERFORMANCE_TESTS` | Enables performance tests when the performance package is installed.           |

Every editor entry point is grouped under `Tools > Gameplay Ability Toolkit > Dashboard`. Dashboard pages register through `GASDashboardPageRegistry`, which lets modules such as Input, Cues, Tags, Logging, and GameCreator contribute pages without adding more top-level menus.

### Dashboard Page Map

| Dashboard page   | Use it for                                                                                           |
| ---------------- | ---------------------------------------------------------------------------------------------------- |
| **Setup**        | Validate configuration, tag asset, cue library, input library, target inputs, cue pool, and logging. |
| **Authoring**    | Create shared assets and jump into focused authoring pages.                                          |
| **Abilities**    | Generate ability scripts or create ability assets from concrete definition types.                    |
| **Effects**      | Generate effect scripts or create effect assets from concrete definition types.                      |
| **Cues**         | Register cue tags and cue notify assets.                                                             |
| **Tags**         | Analyze and fix tag references.                                                                      |
| **Logging**      | Tune debug output.                                                                                   |
| **Extensions**   | Enable optional integrations and setup helpers.                                                      |
| **Dependencies** | Install/validate dependencies and enable test defines.                                               |

Use the Dashboard first when something looks globally misconfigured. Use actor and asset Inspectors when one actor or one definition behaves incorrectly.

## Next Steps

* Read [Authoring Abilities](/docs/gameplay-ability-toolkit/build-with-it/03-authoring-abilities.md) for the definition/runtime/spec pattern applied to abilities.
* Read [Authoring Effects](/docs/gameplay-ability-toolkit/build-with-it/04-authoring-effects.md) for active specs, stacking, periodic execution, and inhibition.
* Read [Extending the Framework](/docs/gameplay-ability-toolkit/build-with-it/05-extending.md) when you need custom hooks or backends.


---

# 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/02-architecture.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.
