> 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/tutorial-details/howtoaddability.md).

# How To Add an Ability

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

This guide adds a new **Ice Spike** ability to the Basic Tutorial. It intentionally reuses the Fire Skill's targeting and effect shape so you can focus on the toolkit wiring:

```
Definition -> Runtime -> Asset -> Input -> Playtest -> Test
```

After the ability works, replace the reused fire effects with real ice damage, slow, freeze, or other effects by following [Authoring Effects](/docs/gameplay-ability-toolkit/build-with-it/04-authoring-effects.md).

Read [Basic Tutorial](/docs/gameplay-ability-toolkit/try-it/basictutorial.md) first so the scene assets and controls are familiar.

## Before You Start

Confirm these prerequisites in Unity:

1. Open `GameplayAbilityToolkit/Tutorial/Basic/Scenes/BasicTutorial.unity`.
2. Press Play once and confirm the original tutorial abilities work.
3. Exit Play Mode before editing assets or prefabs.
4. Open `Tools > Gameplay Ability Toolkit > Dashboard > Setup` and confirm the project configuration is ready.
5. Keep the Project window focused on `GameplayAbilityToolkit/Tutorial/Basic/`.

This guide assumes you are adding a tutorial-only ability. For production game code, put your new definition/runtime classes in your own game assembly instead of the tutorial assembly.

## What You Will Touch

| Layer        | What you add                                          |
| ------------ | ----------------------------------------------------- |
| Definition   | `BasicTutorialIceSpikeAbility` ScriptableObject type. |
| Runtime      | `BasicTutorialIceSpikeRuntime` activation logic.      |
| Asset        | `GA_IceSpike.asset`.                                  |
| Scene wiring | Granted ability, keyboard input, input binding.       |
| Verification | Play Mode result and optional PlayMode test.          |

## Editor Map

| Step             | Unity location                                          |
| ---------------- | ------------------------------------------------------- |
| Ability code     | `Tutorial/Basic/Scripts/`                               |
| Ability asset    | `Tutorial/Basic/Abilities/`                             |
| Reused effects   | `Tutorial/Basic/Effects/`                               |
| Reused targeting | `Tutorial/Basic/Prefabs/Targeting/`                     |
| Player wiring    | Scene `Player` object or `Prefabs/Actors/Player.prefab` |
| Input library    | `Tutorial/Basic/Inputs/BasicTutorialInputs.asset`       |

The most common mistake is creating the asset correctly but not granting or binding it to the player.

## 1. Create the Definition Class

Create `Scripts/BasicTutorialIceSpikeAbility.cs`:

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

namespace GameplayAbilityToolkit.Tutorial.Basic
{
    [CreateAssetMenu(
        fileName = "GA_IceSpike",
        menuName = "Gameplay Ability Toolkit/Tutorial/Basic/Ice Spike",
        order = 505)]
    public sealed partial class BasicTutorialIceSpikeAbility : BasicTutorialAbilityDefinition
    {
        public override AbilityRuntime CreateRuntime() => new BasicTutorialIceSpikeRuntime();
    }
}
```

`BasicTutorialAbilityDefinition` already exposes the tutorial fields you need: animation clip, duration, hit window, effects, guarded effect variants, target collector prefab, and cue tags.

### After Saving The Script

Return to Unity and wait for compilation. The create menu entry appears only after the script compiles successfully.

If the menu item does not appear:

* Check the Console for compiler errors.
* Confirm the class is in namespace `GameplayAbilityToolkit.Tutorial.Basic`.
* Confirm it derives from `BasicTutorialAbilityDefinition`.
* Confirm the `[CreateAssetMenu]` attribute uses a unique `menuName`.

## 2. Add the Runtime Logic

Tutorial runtimes live in `Scripts/BasicTutorialAbilityRuntimes.cs`. The shared `BasicTutorialTimedAbilityRuntime` handles the windup, hit-window, recovery, and cleanup loop.

For Ice Spike, override `OnHitWindow()` and apply the primary effect to each collected target:

```csharp
public sealed class BasicTutorialIceSpikeRuntime : BasicTutorialTimedAbilityRuntime
{
    protected override void OnHitWindow()
    {
        foreach (var target in CollectTargets())
        {
            Actor.ApplyEffectToTarget(target, TutorialDefinition.primaryEffect);
            Actor.NotifyTargetHit(target);
        }
    }
}
```

Optional upgrades:

* Apply `secondaryEffect` as a second line for a slow, freeze, or DoT.
* Use the guarded variants through the same mitigation helper used by Fire Skill.
* Override additional lifecycle hooks if the ability needs charge, channel, or multi-hit behavior.

### Runtime Boundaries

Keep the runtime focused on activation behavior:

| Put here                                                                        | Keep out                                                                                  |
| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Target collection, effect application, timing, cancellation, event/cue triggers | Permanent actor stats, serialized tuning that belongs on the ability asset, UI-only state |

If Ice Spike needs new numbers, add serialized fields to the definition class or reuse inherited fields. Do not hard-code tuning values in the runtime unless they are truly implementation constants.

## 3. Create and Configure the Asset

In the Project window, choose:

```
Create > Gameplay Ability Toolkit > Tutorial > Basic > Ice Spike
```

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

Save the asset as:

```
GameplayAbilityToolkit/Tutorial/Basic/Abilities/GA_IceSpike.asset
```

The fastest setup is to open `GA_FireSkill.asset` beside it and copy equivalent values.

| Section          | Suggested value                                                                     |
| ---------------- | ----------------------------------------------------------------------------------- |
| Tutorial timing  | Reuse `Player_FireCast`, duration, and hit window.                                  |
| Tutorial effects | Reuse Fire Skill impact effect until you author ice-specific effects.               |
| Targeting        | Reuse Fire Skill's cone collector.                                                  |
| Cost             | Reuse or create a Mana cost effect.                                                 |
| Cooldown         | Set a small cooldown so HUD behavior is visible.                                    |
| Tags             | Reuse an existing skill tag or add `Ability.Skill.Ice` through the dashboard first. |

> If the dashboard reports an unknown tag, add the tag to `BasicTutorialTags.asset` before using it in the ability.

### Inspector Checklist

Select `GA_IceSpike.asset` and check:

* Animation clip is assigned.
* Duration is long enough to reach the hit window.
* Hit window time is inside the duration.
* Primary effect is assigned.
* Target collector prefab is assigned.
* Cost and cooldown are set if you expect UI feedback.
* Tags are valid in `BasicTutorialTags.asset`.

### Asset Naming

Use:

| Asset type               | Prefix   |
| ------------------------ | -------- |
| Ability                  | `GA_`    |
| Effect                   | `GE_`    |
| Attribute set definition | `ASDef_` |
| Attribute set values     | `AS_`    |
| Gameplay cue             | `GC_`    |

Keeping the prefix lets Project search and GitBook screenshots stay readable as the sample grows.

## 4. Wire the Ability Into the Scene

Make three Inspector edits:

| Place                                     | Change                                                 |
| ----------------------------------------- | ------------------------------------------------------ |
| Player `BasicTutorialSetup`               | Add `GA_IceSpike` to **Granted Abilities**.            |
| Player `BasicTutorialKeyboardInputSource` | Add input name `IceSpike` bound to key `F`.            |
| `Inputs/BasicTutorialInputs.asset`        | Add an input binding from `IceSpike` to `GA_IceSpike`. |

The input name must match exactly in the keyboard source and input binding asset.

### Grant The Ability

In the open scene:

1. Select `Player` in the Hierarchy.
2. Find `BasicTutorialSetup` in the Inspector.
3. Expand **Granted Abilities**.
4. Increase the array size by one.
5. Drag `GA_IceSpike.asset` into the new slot.

If you are editing the prefab instead of the scene instance, open `Prefabs/Actors/Player.prefab` and make the same change there.

### Bind The Keyboard Key

Still on the player:

1. Find `BasicTutorialKeyboardInputSource`.
2. Add a binding row.
3. Set `Input Name` to `IceSpike`.
4. Set `Key` to `F`.

This component turns Unity keyboard input into toolkit logical input events.

### Bind The Logical Input To The Ability

Open:

```
GameplayAbilityToolkit/Tutorial/Basic/Inputs/BasicTutorialInputs.asset
```

Add a logical input entry named `IceSpike`, then bind it to `GA_IceSpike.asset` using the same pattern as `FireSkill` and `Heal`.

If pressing F does nothing in Play Mode, inspect this asset first. The key source can fire correctly while the input library still has no ability mapping.

## 5. Prove It Works

Expected Play Mode result:

1. Press F.
2. The event log shows `GA_IceSpike` activation.
3. The cost applies.
4. The hit window resolves.
5. The dummy HP drops.

If the animation plays but damage never lands, inspect the runtime `OnHitWindow()` override and the target collector assignment.

### Debugging Order

Use this order because it follows the runtime path:

1. Console compile errors.
2. `GA_IceSpike.asset` fields.
3. Player granted ability list.
4. Keyboard input source binding.
5. Input library mapping.
6. Target collector prefab.
7. Primary effect assignment.
8. Event log output.

Avoid changing multiple layers at once. Fix the first broken handoff, then press Play again.

## Optional PlayMode Test

Create a PlayMode test that:

* Builds or opens an actor with an ASC.
* Grants `GA_IceSpike`.
* Activates the ability.
* Ticks enough time to reach the hit window.
* Asserts the target attribute changed.

When working in this repository, the core tests under `DevelopmentTests/GameplayAbilityToolkit/Core.Tests/` are the closest examples for ability activation, ticking, and attribute assertions. For tutorial-only content, manual Play Mode verification is usually enough until you add your own project test assembly.

## Checklist

* [ ] `BasicTutorialIceSpikeAbility.cs` defines the ScriptableObject type.
* [ ] `BasicTutorialIceSpikeRuntime` overrides `OnHitWindow()`.
* [ ] Unity recompiles without Console errors.
* [ ] `GA_IceSpike.asset` exists under `Abilities/`.
* [ ] Effects, clip, collector, tags, cost, and cooldown are assigned.
* [ ] Player grants the ability.
* [ ] Keyboard source maps `IceSpike` to F.
* [ ] Input asset binds `IceSpike` to `GA_IceSpike`.
* [ ] Play Mode confirms the dummy HP drops.
* [ ] Optional PlayMode test covers activation and effect application.


---

# 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/tutorial-details/howtoaddability.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.
