Course contentsShow
← Unreal Engine Game Development
Lesson 662 of 8809. Gameplay Ability System (GAS)Free lesson

Implementing Wait Delay and Timer Logic

Manage time-based ability events using built-in task delegates to trigger secondary effects without blocking the game thread.

In this lesson, you will learn how to orchestrate multi-step gameplay effects by leveraging built-in AbilityTask delegates to schedule logic without stalling the game thread.

The Problem with Blocking Logic

When designing complex gameplay abilities—like a "Delayed Fireball" that spawns a projectile two seconds after an animation starts—you must avoid using traditional Delay nodes found in standard Blueprints. Because GameplayAbility logic often spans both client and server, using blocking logic would break the ability's state machine. Instead, we use AbilityTask_WaitDelay, which allows the ability to remain "active" while suspending its specific execution flow until a timer elapses.

Implementing Wait Delay

The WaitDelay task acts as an asynchronous timer that triggers a delegate callback upon completion. This keeps your game loop fluid because the CPU is not trapped in a loop waiting for time to pass; rather, the task registers an event in the engine's internal timer manager and resumes your ability logic only when the signal fires.

Here is how you implement this within your ActivateAbility override:

// 1. Create the task, specifying the duration
UAbilityTask_WaitDelay* WaitTask = UAbilityTask_WaitDelay::WaitDelay(this, 2.0f);

// 2. Bind a delegate to the OnFinish event
WaitTask->OnFinish.AddDynamic(this, &UMyAbility::OnDelayFinished);

// 3. Ready the task to execute
WaitTask->ReadyForActivation();

Inside your OnDelayFinished callback, you can safely perform your secondary effect, such as spawning an actor or applying a GameplayEffect. Because this is an AbilityTask, the GAS framework automatically handles the lifecycle management, ensuring that if the ability is canceled (e.g., the player is stunned) before the two seconds pass, the task is properly cleaned up.

Why use Delegates?

By using delegates, you decouple the "start" of your ability from the "secondary effect." This architecture ensures that your ability remains responsive to external cancellations. If the task finishes, the delegate fires; if the task is interrupted by an end-ability event, the AbilityTask handles the memory cleanup, preventing orphaned timers or invalid pointer access.

Key Takeaway: Always use AbilityTask_WaitDelay instead of standard delays to ensure your abilities remain interruptible, state-aware, and performant within the GAS lifecycle.