# Running ActionSequences

## Overview

This section explains how to execute and control created ActionSequences at runtime.

You can also handle various situations that occur during playback by connecting scripts to Collision, Event, and Trigger tracks, and manage execution states through ActionRunner.

## Controlling ActionSequence Execution

### Play

```lua
local ActionRunner = Humanoid:GetActionRunner()
local ActionSequenceKey = "AttackAction"

ActionRunner:Play(ActionSequenceKey)
```

The Play method can only be called when the **character is not dead**, and the **Key value passed must match the name of the ActionSequence instance**.

#### How It Works

When the Play method is called, the original ActionSequence instance is **duplicated under Humanoid.ActionRunner**, and the action is executed based on the duplicated instance. Understanding how ActionSequence works allows you to create and control various directions through scripts. For more details, refer to the runtime behavior section below.

{% content-ref url="actionsequence-mechanism" %}
[actionsequence-mechanism](https://docs.overdare.com/manual/studio-manual/game-development/actionsequence/actionsequence-mechanism)
{% endcontent-ref %}

### Transition Playback

```lua
local ActionRunner = Humanoid:GetActionRunner()
local ActionSequenceKey = "AttackAction"
local TransitionTime = 0.5 -- If greater than 0, it is processed as transition playback.

ActionRunner:Play(ActionSequenceKey, TransitionTime)
```

If the **TransitionTime value passed to the Play method is greater than 0**, ActionSequence plays with a smooth transition (blending) from the current action to the new action.\
(If TransitionTime is 0 or omitted, the current action A ends immediately without transition, and action B starts playing right away.)

When transition playback occurs, if action B is executed while action A is already playing, both actions are played **simultaneously for a certain period and gradually transition**. During the TransitionTime, blending occurs from A to B, after which A ends and only B remains.

<figure><img src="https://2064130887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhrvYlLq1mQAq0V0vwPsb%2Fuploads%2For9EUQRMJ8JdLBkJWulG%2FActionSequencer-Transition.png?alt=media&#x26;token=9cdeef9e-d662-4967-935a-79a35d81242e" alt=""><figcaption></figcaption></figure>

TransitionTime represents the **maximum duration** in which a transition can occur. The actual blending time may vary depending on the remaining playback time of A at the moment the transition starts and the total duration of B. In this case, the transition time is clamped to the shorter duration between the remaining time of A and the total duration of B.

This approach helps prevent abrupt transitions between actions and enables more natural direction.

#### Per-Track Transition Behavior

When TransitionTime is greater than 0, transitions are handled differently depending on the track type.

<table><thead><tr><th width="207.3333740234375">Track</th><th>Behavior</th></tr></thead><tbody><tr><td>Animation Track</td><td>Blending between A → B is performed based on TransitionTime. If multiple animations exist at the same time, the last animation is applied based on playback timing and track structure.</td></tr><tr><td>Sound Track</td><td>The existing sound (A) fades out based on TransitionTime.</td></tr><tr><td>CameraShake Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Camera FOV Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Camera Zoom Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Control Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Collision Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Event Track</td><td>The existing track (A) ends immediately, and the new track (B) starts.</td></tr><tr><td>Trigger Track</td><td>The existing track (A) ends immediately, and the new track (B) starts. However, for triggers that have already been entered but not exited, the exit event is called immediately.</td></tr></tbody></table>

#### Notes

* **A maximum of two** ActionSequences can be played simultaneously.
* If a new action is executed while two ActionSequences are already playing, the oldest currently playing action will be terminated.

### Get Playing ActionSequences

```lua
local ActionRunner = Humanoid:GetActionRunner()
local Actions = ActionRunner:GetActionSequences() 
```

Retrieves the **currently playing** ActionSequences set in the ActionRunner.

Depending on the transition state, multiple ActionSequences may exist simultaneously, so the result is returned as an array.

The returned array is **ordered from previously played ActionSequences to those that will be played next**, and completed entries are automatically removed.

The GetActionSequences method **can only be called on the server**.

### Stop

```lua
local ActionRunner = Humanoid:GetActionRunner()

ActionRunner:Stop("SomeActionName") -- Stop a specific ActionSequence
ActionRunner:StopAll() -- Stop all currently playing ActionSequences
```

You can stop a specific ActionSequence or stop all ActionSequences at once.

During a transition, both the previous action (A) and the next action (B) may exist simultaneously. In this state, if B is stopped, the transition target is removed, which may also cause A to be stopped.

If a transition occurs between ActionSequences with the same name (A → A), Stop behaves the same as StopAll.

For Trigger Tracks, if the ActionSequence is stopped after entering a section but before exiting it, the exit event is triggered immediately.

## ActionRunner Events

The execution state of an ActionSequence can be checked through events provided by the ActionRunner.

```lua
local ActionRunner = Humanoid:GetActionRunner()

-- self : The character model that executed the ActionSequence is passed.
-- key : The Key (name) of the finished ActionSequence is passed.
local function OnEnded(self, key)
    -- ...
end
ActionRunner.Ended:Connect(OnEnded) 

-- self : The character model that executed the ActionSequence is passed.
-- key : The Key (name) of the finished ActionSequence is passed.
local function OnStopped(self, key)
    -- ...
end
ActionRunner.Stopped:Connect(OnStopped) 
```

* **Ended event**: Called when the ActionSequence **finishes playing normally.**
* **Stopped event**: Called when the ActionSequence is **interrupted before completion**. It is also triggered when ended via Stop or StopAll methods, and regardless of whether a transition is used, it is called immediately for the existing action when a new action starts playing.

## Connecting ActionSequence Events

You can execute required logic during playback by connecting scripts to Collision, Event, and Trigger tracks.

**Event connection scripts must be children of the ActionSequence instance** and should be referenced using **relative paths** such as `script.Parent`. Since ActionSequence operates as a duplicated instance at runtime, using non-relative references will not apply to the actual runtime instance (the clone).

```lua
-- Good
local ActionSequence = script.Parent
ActionSequence:Hit("CollisionEventName"):Connect(function(self, other)
    -- ...
end)

-- Bad (Not Work)
local ActionSequence = game.ActionSequenceService.SomeActionSequence
ActionSequence:Hit("CollisionEventName"):Connect(function(self, other)
    -- ...
end)
```

Events can be connected in both server and client environments. However, **server-side Scripts are recommended to be placed directly under the ActionSequence**, as they may not function properly when placed deeper in the hierarchy.

**If events are connected in a LocalScript under the ActionSequence, the logic will be executed on all clients**. Therefore, you should filter based on the executor (self) of the ActionSequence when necessary.

### Collision Track Integration

```lua
local ActionSequence = script.Parent

-- self : The character model that executed the ActionSequence is passed.
-- other : The target object detected by the collision check (character model or Part) is passed.
ActionSequence:Hit("CollisionEventName"):Connect(function(self, other)
    -- ...
end)
```

The target object (`other`) passed through a collision event may **include the executor (**`self`**) of the ActionSequence**. Therefore, you should filter out the executor when necessary.

This is used for **target-based interaction logic** such as applying damage or healing to objects hit by the collider.

### Event Track Integration

```lua
local ActionSequence = script.Parent

-- self : The character model that executed the ActionSequence is passed.
ActionSequence:GetMarkerReachedSignal("EventName"):Connect(function(self)
    -- ...
end)
```

This is used when you need to execute a script at a specific point during action playback.

For example, it can be used for **timing-based logic** such as handling jump start/landing timing or skill preparation/casting timing.

### Trigger Track Integration

```lua
local ActionSequence = script.Parent

-- self : The character model that executed the ActionSequence is passed.
ActionSequence:TriggerStarted("TriggerName"):Connect(function(self)
    -- ...
end)

-- self : The character model that executed the ActionSequence is passed.
ActionSequence:TriggerEnded("TriggerName"):Connect(function(self)
    -- ...
end) 
```

This is used for logic that enables or disables a state during a specific duration.

For example, it can be used for **duration-based state control** such as parrying, invincibility, or hit detection.
