Using Timers

A How-To Guide on Using Timers for Gameplay in Blueprint and C++ for Unreal Engine.

Choose your operating system:

Windows

macOS

Linux

Timers perform actions either after a delay period or continuously over a period of time. For example, you may want to make a Player Character invincible after obtaining a certain item and revert them to a state of vulnerability after a few seconds. Alternatively, you may want to apply damage every second to a player that is standing in a fire. In this How-To guide, you will be tasked with implementing a Timer for the Player Character which will result in it catching fire and taking damage if it walks into the Fire Effect Actor's volume. If the player stands in the fire for too long, it will explode and be destroyed.

Choose your implementation method:

Blueprints

C++

Project Setup

  1. Begin by creating a New > Games > Third-Person > Blueprint Project with Starter Content Enabled named Timers.

The Third-person template project provides a third-person Character that is already mapped to receive input. Additionally, setting up your project with Starter Content provides access to different sounds and particle effects such as fire.

image0.png

Drop down for toggling the project type (1), the dropdown for enabling starter content (2), name field for the project, (4) the Create Project button for initializing the project,

Creating The Fire Effect Actor

The Fire Effect Actor exists as a Blueprint class in the Starter Content folder. It contains a ParticleSystemComponent for the fire effect, and an AudioComponent for the fire's sound. It will also be necessary for you to set the value of the Fire Effect's Initial Lifespan. When an Actor's lifespan expires, it will be destroyed.

For additional documentation refer to the Actor Lifecycle

  1. Navigate to Content > Stater Content > Blueprints and double-click the Blueprint_Effect_Fire to open its Class Defaults.

    image1.png

  2. In the Details panel, navigate to the Actor category then set the Initial LifeSpan variable to the value of 1.5.

    image2.png

  3. Click Compile and Save.

    image3.png

Finished Blueprint

image4.png

Creating the Explosion Effect

The Explosion Effect Actor exists as a Blueprint class in the Starter Content folder. It contains a Particle System Component for the explosion effects, and an Audio Component for the explosion sound It will also be necessary for you to set the value of the Explosion Effect's Initial Lifespan variable. When an Actor's lifespan expires it will be destroyed from Gameplay.

  1. Navigate to Content > Stater Content > Blueprints and double-click the Blueprint_Effect_Fire to open its Class Defaults.

    image5.png

  2. In the Details panel, navigate to the Actor category then set the Initial LifeSpan variable to the value of 1.5**.

    image2.png

  3. Click Compile and Save.

    image3.png

Finished Blueprint

image6.png

Creating the Fire Effect Actor

The Fire Effect Actor functions as a particle effect that exists in a physical location within your Level. You will implement the functionality for when your Player Character overlaps the Fire Effect Actor which causes it to catch fire and receive damage over time. In order to do this, you will need to create the following class members:

Class Member

Description

BoxComponent

A box used as a collision volume for the Fire Effect Actor. When another Actor overlaps its bounds, the NotifyActorBeginOverlap function will be called.

ParticleSystemComponent

A particle emitter that provides the visual fire effect.

NotifyActorBeginOverlap

An Event that triggers when this Actor overlaps another Actor/ For example, when a player walks into the box component used for the Fire Effect Actor's overlap bounds.

NotifyEndActorOverlap

An Event that triggers when an Actor no longer overlaps another Actor, and they have separated. For example when a player exits the box component used for the Fire Effect Actor's overlap bounds.

  1. Navigate to the Content Browser and click the Add/Import button. From the dropdown menu select Create a Blueprint Class, and select Actor from the Pick Parent Class window.

    image7.png

  2. From the Class Defaults, navigate to the Components panel and click Add Component button, then search for and select Box Collision. Name this Box Collision Shape to OverlapVolume.

    image10.png

  3. Click the Add Component button, then search for and select for Particle System.

    image11.png

  4. In the Details panel for the Particle System, navigate to the Particles category. Select the arrow next to the Template variable to reveal the dropdown asset window. Search and select for the P_Fire particle asset.

    image12.png

  5. In the Event Graph, right-click and from the Actions dropdown menu search for and select Actor Begin Overlap.

    image13.png

  6. From the Event ActorBeginOverlap node, drag from the Other Actor output pin, and from the dropdown menu, search for and select Cast To Third Person Bp Character.

    image14.png

  7. From the Cast To ThirdPersonCharacter node, drag from the As Third Person Character output pin, and from the dropdown menu search for and select the Ignite Fire Timer function.

    image15.png

  8. In the Event Graph, right-click and from the Actions dropdown menu search for and select ActorEndOverlap.

    image16.png

  9. From the Event ActorEndOverlap node, drag from the Other Actor output pin, and from the dropdown menu, search for and select Cast To Third Person Character.

    image17.png

  10. From the Cast To ThirdPersonCharacter node, drag from the As Third Person Character output pin, and from the dropdown menu search for and select the Clear Fire Timer function.

    image18.png

  11. Click Compile and Save.

    image3.png )

Finished Blueprint

image20.png

Implementing the Player Character

The Third-Person template comes complete with a Player Character class. This class is designed to use movement logic when the input keys that are mapped to its Character Movement Component are pressed. This is useful behavior for physically moving your character onto the overlap bounds of the Fire Actor. However, you will be tasked with creating additional functionality with the following class members.

Class Member

Description

float Health

A float variable to represent the Player's health.

FTimerHandle

A struct with a unique handle to distinguish between EventDispatchers and Delegates. The Timer Handle will manage a TakeFireDamage function to call over a specified amount of time.

TakeFireDamage()

A function which depletes the player's health by a specified amount of damage. If the player's health reaches zero, then an Explosion Actor will spawn and the Player Character will be destroyed.

IgniteFireTimer()

A function that spawns a FireEffect Actor onto the Player Character, and causes the Timer Handle to call the TakeFireDamage function.

ClearFireTimer()

A function that will clear the Timer Handle, and prevent it from calling the TakeFireDamage function.

  1. From the Content Browser, double-click the ThirdPersonCharacter Blueprint to open its Class Defaults.

    image21.png

  2. Navigate to the My Blueprint panel and from the variables category, click the Add (+) button to add a new float variable named Health.

    image22.png

  3. Compile your Blueprint, then with your Health float variable selected, navigate to the Details panel and set its Health value to 100.0.

    image23.png

  4. Navigate back to the My Blueprint tab and from the Variables category, click the Add (+) button to create a new variable of type TimerHandle named FireTimer.

    image24.png

  5. Navigate back to the My Blueprint tab and from the Functions category, click the Add (+) button to create three functions with the names: TakeFireDamage, IgniteFireTimer, and ClearFireTimer.

    image25.png

The Add (+)button to create a new function. (2) The three newly created functions: TakeFireDamage, IgniteFireTimer, and ClearFireTimer.

Implementing the TakeFire Damage Function.

  1. With the TakeFireDamage function tab open, navigate to the My Blueprint panel and drag your Health variable onto the Event Graph to create a reference node.

    image26.png

  2. Drag from the Health variable pin and, from the actions menu, search for and select the float - float node.

    image27.png

  3. Set the deduction value to the amount of damage you want to inflict to your Player Character, in this example we chose the value -20.0.

    image28.png

  4. Navigate back to the My Blueprint panel, then drag your Health variable onto the Event Graph to create a reference node.

    image29.png

  5. Drag from the Health pin and from the Executable actions menu, search for and select the float <= float (less than or equal to) operator.

    image30.png

  6. Drag from the Take Fire Damage node's execution pin, and from the Executable actions menu search for and select Branch.

    image31.png

  7. Navigate to the My Blueprint panel, and drag a copy of the Health variable over the return value of the float - float node. This will set the Health variable to the result of this node's operation.

    image32.png

  8. Connect the return value pin from the Health <= 0 Operator node into the Conditional pin of the Branch node. Then, connect the False output pin into the Set input pin from the Set Health node.

    image33.png

  9. Drag from the True execution pin from the Branch node, then from the Executable actions menu search for and select Spawn Actor From Class. Then, from the class pin, search for and select the Blueprint_Explosion_Effect.

    image34.png

  10. From the SpawnActor Blueprint Effect Explosion node, drag from the Spawn Transform pin, then from the Executable actions menu search for and select Get Actor Transform.

    image35.png

  11. Drag from the SpawnActor Blueprint Effect Explosion node's execution pin, then from the Executable actions menu, search for and select DestroyActor.

    image36.png

  12. Click Compile and Save.

    image3.png

In-Progress Blueprint

image38.png

Implementing the IgniteFireTimer Function

  1. Open the IgniteFireTimer function graph. Drag the execution pin from the Ignite Fire Timer node and from the Executable actions menu, search for and select Spawn Actor From Class. Then, from the class pin, search for and select Blueprint_Fire_Effect.

    image39.png

  2. From the SpawnActor Blueprint Fire Effect node, drag from the Spawn Transform pin. Then, from the Executable actions menu, search for and select Get Actor Transform.

    image40.png

  3. Drag from the SpawnActor Blueprint Fire Effect node return value pin. Then, from the Executable actions menu, search for and select AttachActorToComponent.

    image41.png

  4. In the AttachActorToComponent node, navigate to the Socket Name pinand set it to spine_01. Next, set the Location Rule pin to Snap to Target, and the Rotation Rule and Scale Rule to Keep Relative. Then, click to check the box which enables the Weld Simulated Bodies boolean to true.

    image42.png

  5. Drag from the AttachActorToComponent node's Parent pin, then from the Executable actions menu search for and select Get Mesh.

    image43.png

  6. Drag from the AttachToActorComponent node's execution pin, then from the Executable actions menu, search for and select for Set Timer By Function Name. Next, set the Function Name pin to TakeFireDamage and the Time pin to 0.75. Lastly, click to check the box which enables the Looping boolean to true.

    image44.png

  7. From the Set Timer By Function Name node, drag from the Timer Handle Return Value pin and from the Executable actions menu search for and select Set Fire Timer.

    image45.png

  8. Click Compile and Save.

    image3.png

In-Progress Blueprint

image47.png

Implementing the ClearFireTimer Function

  1. Open the ClearFireTimer function graph. From the My Blueprint panel, drag the FireTimer variable into the Event Graph.

    image48.png

  2. Drag from the Fire Timer pin and from the Executable actions menu, search for and select Clear and Invalidate Timer by Handle.

    image49.png

  3. Click Compile and Save.

    image3.png

In-Progress Blueprint

image51.png

Finished Blueprint

image52.png

End Result

  1. From the Content Browser, drag an instance of your Bp_FireActor into the Level.

    image53.png

  2. Navigate to the Editor Toolbar then click Play (PIE) to preview your project in the editor.

    image54.png

Using the Arrow or WASD keys, move your character into the Fire Effect Actor's volume. If you remain in the volume for too long, your character's health will eventually deplete to zero, at which point the character will explode.

EndResult.gif

Additional Timer-Related Nodes

While the Set Timer by Function Name and Clear Timer by Handle nodes are used to start and stop a Timer, the nodes below may also be useful depending on your needs.

Get Timer Elapsed and Get Timer Remaining

image56.jpg

The Get Timer Elapsed by Handle and Get Timer Remaining by Handle nodes return the amount of time that has elapsed since starting, and get the amount of time remaining for the specified Timer (indicated by the handle) respectively. They return the value as a Float and can be used for several different purposes, such as when changing an effect over time or when displaying a message before an effect is about to expire.

Pause Timer and Unpause Timer

image57.jpg

The Pause Timer by Handle pauses the timer at its current time and the Clear Timer by Handle stops the timer completely and resets it. The Unpause Timer by Handle node can be used to resume a paused timer and continue it from where it stopped. For example, if a player has an effect applied to them that expires after a timer and they enter a menu or inventory screen, then you may want to pause the effect and resume it when they return to gameplay.

Timer Exists, Is Timer Active, and Is Timer Paused

image58.jpg

The Does Timer Exist by Handle, Is Timer Active by Handle, and Is Timer Paused by Handle nodes all return a True or False value and can be used to determine if a Timer exists, if a Timer is currently active, or if a Timer is currently paused respectively.

Set Timer by Event

image59.jpg

The Set Timer by Event node functions similar to the Set Timer by Function Name node but rather than specifying a function, you can connect a Custom Event node which will be triggered. You can set this to loop as well, just as you can with the Set Timer by Function Name node.

Project Setup

  1. Begin by creating a Begin by creating a New > Games > Third-Person > C++ project with Starter Content Enabled. Name your project Timers.

The Third-person template project provides a third-person Character that is already mapped to receive input. Additionally, setting up your project with Starter Content provides access to different sounds and particle effects such as fire.

image60.png

Drop down for toggling the project type (1), the dropdown for enabling starter content (2), name field for the project, (4) the Create Project button for initializing the project,

Creating the Fire Effect Actor

The Fire Effect Actor is a Blueprint class in the Starter Content folder. It contains a UParticleSystemComponent for the fire effect, and an UAudioComponent for the fire audio. It will also be necessary for you to create a C++ version of the class to spawn the fire effect on the TimerCharacter class when the Player Character overlaps with the Fire Effect Actor.

  1. Click the Add/Import button from the Content Browser, then select New C++ Class to create a new Actor class named FireEffect.

image61.png

  1. In the class defaults of your Fire Effect.h file, declare the following classes:

    protected:
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UParticleSystemComponent* FireParticle;
    
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UAudioComponent* FireAudio;
  2. Navigate to your FireEffect.cpp file, and include the following class libraries to instantiate your component class members:

    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"
  3. In the FireEffect::FireEffect constructor, instantiate and attach the following class members:

    // Sets default values
    AFireEffect::AFireEffect()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    
        //Instantiate our Actor Components
        FireParticle = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticle"));
        FireAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("FireAudio"));
    
        //Sets the Audio Component to be attached to the FireParticle effect
        FireAudio->SetupAttachment(FireParticle);
    
        static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Fire.P_Fire'"));
        FireParticle->SetTemplate(ParticleAsset.Object);
    
        static ConstructorHelpers::FObjectFinder<USoundBase>AudioAsset(TEXT("SoundCue'/Game/StarterContent/Audio/Fire01_Cue.Fire01_Cue'"));
        FireAudio->SetSound(AudioAsset.Object);
    }

ConstructorHelpers is a class that provides methods to assign references in Cpp code to Objects found in the Unreal Editor.

  1. Navigate to the FireEffect::BeginPlay method, and implement the following code:

    void AFireEffect::BeginPlay()
    {
        Super::BeginPlay();
        SetLifeSpan(1.5f);
    }

SetLifeSpan is a method inherited from the Actor class which takes a float to set the Initial Lifespan variable. When an Actor's Lifespan expires it will be destroyed. For additional documentation refer to the Actor Lifecycle

  1. Compile your code.

Finished Code

FireEffectActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FireEffect.generated.h"

UCLASS()
class TIMERS_API AFireEffect : public AActor
{
    GENERATED_BODY()
    public: 
    // Sets default values for this actor's properties
    AFireEffect();

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UParticleSystemComponent* FireParticle;

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UAudioComponent* FireAudio;

    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;

    public: 
        // Called every frame
        virtual void Tick(float DeltaTime) override;
};

FireEffectActor.cpp

#include "FireEffect.h"
#include "Particles/ParticleSystemComponent.h"
#include "Components/AudioComponent.h"

// Sets default values
AFireEffect::AFireEffect()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    FireParticle = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticle"));
    FireAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("FireAudio"));

    FireAudio->SetupAttachment(FireParticle);
    static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Fire.P_Fire'"));

    FireParticle->SetTemplate(ParticleAsset.Object);
    static ConstructorHelpers::FObjectFinder<USoundBase>AudioAsset(TEXT("SoundCue'/Game/StarterContent/Audio/Fire01_Cue.Fire01_Cue'"));
    FireAudio->SetSound(AudioAsset.Object);
}

// Called when the game starts or when spawned
void AFireEffect::BeginPlay()
{
    Super::BeginPlay();
    SetLifeSpan(1.5f);
}

// Called every frame
void AFireEffect::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

Creating the Explosion Effect Actor

The Explosion Effect Actor exists as a Blueprint class in the Starter Content folder. It contains a Particle System Component for the explosion effect, and an Audio Component for the explosion's sound. It will also be necessary for you to create a C++ version of the class to achieve the intended gameplay functionality of spawning the explosion effect on the TimerCharacter class when the Player Character's health reaches zero.

  1. Click the Add/Import button from the Content Browser, then select New C++ Class to create a new Actor class named ExplosionEffect.

    image61.png

  2. In the class defaults of your ExplosionEffect.h file declare the following

    protected:
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UParticleSystemComponent* ExplosionParticle;
    
    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UAudioComponent* ExplosionAudio;
  3. Navigate to your ExplosionEffect.cpp file then include the following class libraries to instantiate your class members.

    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"
  4. In the ExplosionEffect::ExplosionEffect constructor, implement the following class members.

    // Sets default values
    AExplosionEffect::AExplosionEffect()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    
        //Initiate Actor Components
        ExplosionParticle = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("ExplosionParticle"));
        ExplosionAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("ExplosionAudio"));
    
        //Set the Audio Component to the ExplosionParticle effect
        ExplosionAudio->SetupAttachment(ExplosionParticle);
    
        static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Explosion.P_Explosion'"));
        ExplosionParticle->SetTemplate(ParticleAsset.Object);
        static ConstructorHelpers::FObjectFinder<USoundBase>AudioAsset(TEXT("SoundCue'/Game/StarterContent/Audio/Explosion_Cue.Explosion_Cue'"));
    
        ExplosionAudio->SetSound(AudioAsset.Object);
    }
  5. Next, navigate to the ExplosionEfect::BeginPlay method, and implement the following code:

    void AExplosionEffect::BeginPlay()
    {
        Super::BeginPlay();
        SetLifeSpan(1.5f);
    }
  6. Compile your code.

Finished Code

ExplosionEffect.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ExplosionEffect.generated.h"

UCLASS()
class TIMERS_API AExplosionEffect : public AActor
{
    GENERATED_BODY()
public: 
    // Sets default values for this actor's properties
    AExplosionEffect();
protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
    class UParticleSystemComponent* ExplosionParticle;

    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UAudioComponent* ExplosionAudio;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};

ExplosionEffect.cpp

    #include "ExplosionEffect.h"
    #include "Components/AudioComponent.h"
    #include "Particles/ParticleSystemComponent.h"

    // Sets default values
    AExplosionEffect::AExplosionEffect()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;

        ExplosionParticle = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticle"));

        ExplosionAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("FireAudio"));    

        ExplosionAudio->SetupAttachment(ExplosionParticle);

        static  ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Explosion.P_Explosion'"));

        ExplosionParticle->SetTemplate(ParticleAsset.Object);

        static ConstructorHelpers::FObjectFinder<USoundBase>AudioAsset(TEXT("SoundCue'/Game/StarterContent/Audio/Explosion_Cue.Explosion_Cue'"));

        ExplosionAudio->SetSound(AudioAsset.Object);
    }

    // Called when the game starts or when spawned
    void AExplosionEffect::BeginPlay()
    {
        Super::BeginPlay();
        SetLifeSpan(1.5);
    }

    // Called every frame
    void AExplosionEffect::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    }

Implementing the Player Character Class

The Third-Person template includes a Player Character class. This class is designed to use movement logic when its input keys are pressed. This is useful when moving your character onto the overlap bounds of the Fire Effect Actor. You will also be tasked with creating additional functionality using the following class members.

Class Member

Description

float Health

A float variable to represent the player's health.

FTimerHandle

A struct with a unique handle to distinguish between Delegates.The Timer Handle will manage a TakeFireDamage function to call over a specified amount of time.

void TakeFireDamage()

A function that depletes the player's health by a specified amount of damage, if the player's health reaches zero, then an Explosion Actor will spawn and the Player Character will be destroyed

void IgniteFireTimer()

A function that spawns a FireEffect Actor onto the Player Character, and sets the Timer Handle to call the TakeFireDamage function.

void ClearFireTimer()

A function that clears the Timer Handle, preventing it from calling the TakeFireDamage function.

FTimerDelegate

A Delegate template that can call member functions on C++ Objects in a generic, type-safe way.

  1. Begin by navigating to the C++ classes folder and double-clicking your TimerCharacter class to open its TimerCharacter.h file.

  2. In the class definition, declare the following:

    protected:
      FTimerHandle FireTimer;
    
      FTimerDelegate FireDelegate;
    
      UPROPERTY(BlueprintReadOnly)
      float Health;
    
      //Depletes Player Health
      UFUNCTION()
      void TakeFireDamage();
    
    public:
    //Invoke the Firetimer and spawn the fire effect Actor 
    void IgniteFireTimer();
    
    //Clear the FireTimer Handle
    void ClearFireTimer();
  3. Navigate to your TimerCharacter.cpp file and add the following class libraries:

        #include "Kismet/GameplayStatics.h"
        #include "FireEffect.h"
        #include "ExplosionEffect.h"
  4. In the constructor of your TimerCharacter::FireActor class, declare the following code:

        //Sets default values
        AFireActor::AFireActor()
        {   
            //Instantiate Actor Components.
            RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    
            OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume"));
            FireParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticleComp"));
    
            //Attaching Actor Components onto the Root.
            OverlapVolume->SetupAttachment(RootComponent);
    
            FireParticleComp->SetupAttachment(OverlapVolume);
    
            //Sets the Size of the Overlap Volume.
            OverlapVolume->SetBoxExtent(FVector(256, 256, 128));
        }
  5. Implement the ATimersCharacter::TakeFireDamage function by declaring the following code:

    void ATimersCharacter::TakeFireDamage()
    {
        if (Health <= 0)
        {
    
        //Actor's health has reached 0 or below. Spawn Explosion Effect 
        GetWorld()->SpawnActor<AExplosionEffect>(GetActorLocation(), GetActorRotation());
    
        //Destroy Actor
        Destroy();
        }
        else
        {
            //Actor is on fire, executing fire damage.
            Health = (Health - 20.0f);
        }
    
    }

Timers are canceled automatically if the Object they are attached to is destroyed. In this case, when the Player character is destroyed, the Timer Handle becomes invalid and the function will not be called.

  1. Implement the following code logic for the ATimersCharacter::IgniteFireTimer function:

    void ATimersCharacter::IgniteFireTimer()
    {
            GetWorldTimerManager().SetTimer(FireTimer, FireDelegate, 0.75f, true);
            AActor* TempFireEffect = GetWorld()->SpawnActor<AFireEffect>(GetActorLocation(), GetActorRotation());
            TempFireEffect->AttachToActor(this, FAttachmentTransformRules::SnapToTargetIncludingScale);
    }

The SetTimer function of the FTimerManager class will set a timer to call a function or delegate after a delay and can be set to repeat that function call indefinitely. These functions will create a Timer Handle (FTimerHandle), which can be used to pause and resume the countdown, to query or change the amount of time remaining, and to cancel the timer. It is safe to set timers within a function that a timer calls, including the reuse of the Timer Handle that was used to call the function. Additionally, tTimers can run on the next frame rather than within a timed interval. This is done accomplished by calling SetTimerForNextTick, although but this function does not create fill out a Timer Handle.

7.Last, implement the following definition for the ATimersCharacter::ClearFireTimer function:

void ATimersCharacter::ClearFireTimer()
{
    GetWorldTimerManager().ClearTimer(FireTimer);   
}

The Fire Timer Handle will now be invalid, however, you could reuse the handle to manage a new timer. Calling SetTimer with an existing Timer Handle will clear the timer referenced by that Timer Handle and replace it with a new one.

Sample Example:

void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    // Call RepeatingFunction once per second, starting two seconds from now.
    GetWorldTimerManager().SetTimer(MemberTimerHandle, this, &AMyActor::RepeatingFunction, 1.0f, true, 2.0f);
}

void AMyActor::RepeatingFunction()
{
    // Once we've called this function enough times, clear the Timer.
    if (--RepeatingCallsRemaining <= 0)
        {
            GetWorldTimerManager().ClearTimer(MemberTimerHandle);
            // MemberTimerHandle can now be reused for any other Timer.
        }
    // Do something here...
 }

Finished Code

TimersCharacter.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "TimersCharacter.generated.h"

UCLASS(config=Game)
class ATimersCharacter : public ACharacter
{
    GENERATED_BODY()
    /** Camera boom positioning the camera behind the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* CameraBoom;

    /** Follow camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* FollowCamera;

public:
    ATimersCharacter();

    /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)

    float BaseTurnRate;
    /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseLookUpRate;

protected:
    virtual void BeginPlay() override;

    /** Resets HMD orientation in VR. */
    void OnResetVR();

    /** Called for forwards/backward input */
    void MoveForward(float Value);

    /** Called for side to side input */
    void MoveRight(float Value);

    /*** Called via input to turn at a given rate.
    *@param Rate    This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void TurnAtRate(float Rate);

    /**
     * Called via input to turn look up/down at a given rate. 
     * @param Rate  This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void LookUpAtRate(float Rate);

    /** Handler for when a touch input begins. */
    void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);

    /** Handler for when a touch input stops. */
    void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);

     FTimerHandle FireTimer;

     FTimerDelegate FireDelegate;

     UPROPERTY(BlueprintReadOnly)
     float Health;

     UFUNCTION()
     void TakeFireDamage();

protected:
    // APawn interface
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    // End of APawn interface

public:
    /** Returns CameraBoom subobject **/
    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

    /** Returns FollowCamera subobject **/
    FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }

    //Sets FireTimer to call TakeFireDamage function
    void IgniteFireTimer();

    //Clears FireTimer from being called.
    void ClearFireTimer();
};

TimersCharacter.cpp

#include "TimersCharacter.h"
#include "HeadMountedDisplayFunctionLibrary.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Controller.h"
#include "GameFramework/SpringArmComponent.h"
#include "Kismet/GameplayStatics.h"
#include "FireEffect.h"
#include "ExplosionEffect.h"

// ATimersCharacter
ATimersCharacter::ATimersCharacter()
{
    // Set size for collision capsule
    GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

    // set our turn rates for input
    BaseTurnRate = 45.f;

    BaseLookUpRate = 45.f;

    // Don't rotate when the controller rotates. Let that just affect the camera.
    bUseControllerRotationPitch = false;

    bUseControllerRotationYaw = false;

    bUseControllerRotationRoll = false;

    // Configure character movement
    GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...   

    GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate

    GetCharacterMovement()->JumpZVelocity = 600.f;

    GetCharacterMovement()->AirControl = 0.2f;

    // Create a camera boom (pulls in towards the player if there is a collision)
    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));

    CameraBoom->SetupAttachment(RootComponent);

    CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character   

    CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller

    // Create a follow camera
    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));

    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation

    FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

    Health = 100.0f;

    // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
    // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}

    void ATimersCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
        // Set up gameplay key bindings
        check(PlayerInputComponent);

        PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
        PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
        PlayerInputComponent->BindAxis("MoveForward", this, &ATimersCharacter::MoveForward);
        PlayerInputComponent->BindAxis("MoveRight", this, &ATimersCharacter::MoveRight);

        // We have 2 versions of the rotation bindings to handle different kinds of devices differently
        // "turn" handles devices that provide an absolute delta, such as a mouse.
        // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
        PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
        PlayerInputComponent->BindAxis("TurnRate", this, &ATimersCharacter::TurnAtRate);
        PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
        PlayerInputComponent->BindAxis("LookUpRate", this, &ATimersCharacter::LookUpAtRate);

        // handle touch devices
        PlayerInputComponent->BindTouch(IE_Pressed, this, &ATimersCharacter::TouchStarted);
        PlayerInputComponent->BindTouch(IE_Released, this, &ATimersCharacter::TouchStopped);

        // VR headset functionality
        PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this, &ATimersCharacter::OnResetVR);
    }

    void ATimersCharacter::BeginPlay()
    {
        Super::BeginPlay();
        FireDelegate.BindUFunction(this, FName("TakeFireDamage"));
    }

    void ATimersCharacter::OnResetVR()
    {
        UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();
    }

    void ATimersCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
    {
        Jump();
    }

    void ATimersCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)
    {
        StopJumping();
    }

    void ATimersCharacter::TakeFireDamage()
    {
        if (Health <= 0)
        {
            GetWorld()->SpawnActor<AExplosionEffect>(GetActorLocation(), GetActorRotation());
            Destroy();
        }
        else
        {
            Health = (Health - 20.0f);
        }
    }

    void ATimersCharacter::IgniteFireTimer()
    {
        GetWorldTimerManager().SetTimer(FireTimer, FireDelegate, 0.75f, true);
        AActor* TempFireEffect = GetWorld()->SpawnActor<AFireEffect>(GetActorLocation(), GetActorRotation());
        TempFireEffect->AttachToActor(this, FAttachmentTransformRules::SnapToTargetIncludingScale);
    }

    void ATimersCharacter::ClearFireTimer()
    {
        GetWorldTimerManager().ClearTimer(FireTimer);
    }   

    void ATimersCharacter::TurnAtRate(float Rate)
    {
        // calculate delta for this frame from the rate information
        AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
    }

    void ATimersCharacter::LookUpAtRate(float Rate)
    {
        // calculate delta for this frame from the rate information
        AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
    }

    void ATimersCharacter::MoveForward(float Value)
    {
        if ((Controller != nullptr) && (Value != 0.0f))
        {
            // find out which way is forward
            const FRotator Rotation = Controller->GetControlRotation();

            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // get forward vector
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

            AddMovementInput(Direction, Value);
        }
    }  

    void ATimersCharacter::MoveRight(float Value)
    {
        if( (Controller != nullptr) && (Value != 0.0f))
        {
            // find out which way is right
            const FRotator Rotation = Controller->GetControlRotation();

            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // get right vector 
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

            // add movement in that direction
            AddMovementInput(Direction, Value);
        }
    }

Creating the Fire Effect Actor

The Fire Effect Actor functions as a particle effect that exists in a physical location within your Level. You will implement the functionality for when your Player Character overlaps the Fire Effect Actor which causes it to catch fire and receive damage over time.

Class Member

Description

UBoxComponent

A Box Component used as a collision volume for the Fire Effect Actor. When another Actor overlaps its bounds, the NotifyActorBeginOverlap function will be called.

UParticleSystemComponent

A particle emitter that provides the visual fire effect.

void NotifyActorBeginOverlap

An event that triggers when this Actor overlaps another Actor. For example, when a player walks into the Box Component used for the Fire Effect Actor's overlap bounds.

void NotifyEndActorOverlap

An event triggered when an Actor no longer overlaps another Actor. For example, when a player exits the Box Component used for the Fire Effect Actor's overlap bounds.

  1. Navigate to your C++ Classes folder, then right-click the Content Browser to create a New C++ Actor class named FireActor.

    image61.png

  2. In the class definition of AFireActor, declare the following:

    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UBoxComponent* OverlapVolume;
    
    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UParticleSystemComponent* FireParticleComp;
    
    //Called when an Actor Overlaps
    virtual void NotifyActorBeginOverlap(AActor* OtherActor);
    
    virtual void NotifyActorEndOverlap(AActor* OtherActor);
  3. Next, navigate to your FireActor.cpp file and include the following class libraries:

    #include "Particles/ParticleSystemComponent.h"
    #include "Components/BoxComponent.h"
    #include "TimersCharacter.h"
  4. In the Fire Actor's constructor, initialize the following class defaults:

    AFireActor::AFireActor()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    
        //Instantiate Actor Components.
        RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    
        OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume"));
    
        FireParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticleComp"));
    
        //Attaching Actor Components onto the Root.
        OverlapVolume->SetupAttachment(RootComponent);
    
        FireParticleComp->SetupAttachment(OverlapVolume);
    
        //Sets FireParticleComp effect to the asset in the starter content folder
        static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Fire.P_Fire'"));
    
        FireParticleComp->SetTemplate(ParticleAsset.Object);
    }
  5. When the Player Character enters the Fire Effect Actor's volume, the Timer Handle should call the TakeFireDamage function. Declare the following code to implement the FireActor::NotifyActorBeginOverlap function:

    void AFireActor::NotifyActorBeginOverlap(AActor* OtherActor)
    {
        ATimersCharacter* TimersCharacterRef = Cast<ATimersCharacter>(OtherActor);
        if (TimersCharacterRef)
        {
            TimersCharacterRef->IgniteFireTimer();
        }
    }
  6. If the Player Character exits the Fire Effect Actor's volume before its health reaches zero, then the Timer Handle will clear itself and stop calling the TakeFireDamage function. Implement a similar code definition for the FireActor::NotifyActorEndOverlap function:

    void AFireActor::NotifyActorEndOverlap(AActor* OtherActor)
    {
        ATimersCharacter* TimersCharacterRef = Cast<ATimersCharacter>(OtherActor);
        if (TimersCharacterRef)
        {
            TimersCharacterRef->ClearFireTimer();
        }
    }

Finished Code

FireActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FireActor.generated.h"

UCLASS()
class TIMERS_API AFireActor : public AActor
{
    GENERATED_BODY()
public: 
    // Sets default values for this actor's properties
    AFireActor();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UBoxComponent* OverlapVolume;

    UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
    class UParticleSystemComponent* FireParticleComp;

    virtual void NotifyActorBeginOverlap(AActor* OtherActor);
    virtual void NotifyActorEndOverlap(AActor* OtherActor);

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};

FireActor.Cpp

#include "FireActor.h"
#include "Particles/ParticleSystemComponent.h"
#include "Components/BoxComponent.h"
#include "TimersCharacter.h"

// Sets default values
AFireActor::AFireActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    //Instantiate Actor Components.
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));

    OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume"));

    FireParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("FireParticleComp"));

    //Attaching Actor Components onto the Root.
    OverlapVolume->SetupAttachment(RootComponent);

    FireParticleComp->SetupAttachment(OverlapVolume);

    //Sets FireParticleComp effect to the asset in the starter content folder
    static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Fire.P_Fire'"));

    FireParticleComp->SetTemplate(ParticleAsset.Object);
}

// Called when the game starts or when spawned
void AFireActor::BeginPlay()
{
    Super::BeginPlay();
}

void AFireActor::NotifyActorBeginOverlap(AActor* OtherActor)
{
    ATimersCharacter* TimersCharacterRef = Cast<ATimersCharacter>(OtherActor);
    if (TimersCharacterRef)
    {
        TimersCharacterRef->IgniteFireTimer();
    }
}

void AFireActor::NotifyActorEndOverlap(AActor* OtherActor)
{
    ATimersCharacter* TimersCharacterRef = Cast<ATimersCharacter>(OtherActor);
    if (TimersCharacterRef)
    {
        TimersCharacterRef->ClearFireTimer();
    }
}

// Called every frame
void AFireActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

End Result

  1. From the Content Browser, navigate to your C++ Classes folder, right-click your FireActor class, and select Create a Blueprint Class based on FireActor.

    image63.png

  2. Drag an instance of your Bp_FireActor into the Level.

    image64.png

  3. Navigate to the Editor Toolbar then click Play (PIE) to preview your project in the editor.

    image65.png

Using the Arrow or WASD keys, move your character into the Fire Effect Actor's volume. If you remain in the volume for too long, your character's health will eventually deplete to zero, at which point the character will explode.

EndResult.gif

Additional Timer-Related Notes

Timers are managed by a global Timer Manager (of type FTimerManager). A global Timer Manager exists within the Game Instance Object, as well as within each World. Two main functions are used to set up timers with a Timer Manager: SetTimer, and SetTimerForNextTick, both with several overloads. Each one can be attached to any type of Object or function delegate, and SetTimer can be set up to repeat at regular intervals. For additional class methods see the Timer Manager API page Documentation Timers can be used with standard C++ function pointers TFunction Objects or Delegates.

Pausing and Resuming Timers

The FTimerManager function PauseTimer uses a Timer Handle to pause a running timer. This prevents the timer from executing its function call, but the elapsed and remaining times stop incrementing while paused. UnPauseTimer causes a paused timer to resume running.

Timer Information

Timer managers also provide functions for obtaining information, such as the time rate, elapsed time, and remaining time for a specific timer.

IsTimerActive

The IsTimerActive function of the FTimerManager class is used to determine if the specified timer is currently active and not paused.

Example:

// Is this weapon waiting to be able to fire again?
GetWorldTimerManager().IsTimerActive(**this**, &AUTWeapon::RefireCheckTimer);

GetTimerRate

FTimerManager has a function called GetTimerRate that returns the current time rate (time between activations) of a timer from its Timer Handle. A timer's rate cannot be changed directly, however SetTimer can be called with its Timer Handle to clear it and create a duplicated timer with a different rate. GetTimerRate will return a value of -1 if the Timer Handle is not valid.

Example:

// This weapon's rate of fire changes as it warms up. Is it currently waiting to fire, and if so, how long is the current delay between shots?
GetWorldTimerManager().GetTimerRate(**this**, &AUTWeapon::RefireCheckTimer);

GetTimerElapsed and GetTimerRemaining

FTimermanager provides functionality through GetTimerElapsed and GetTimerRemaining, which return the elapsed and remaining time for the timer associated with the provided Timer Handle, respectively. As with GetTimerRate, these functions return -1 if the Timer Handle is invalid.

Example:

// How long will it be until this weapon is ready to fire again? If the answer comes back as -1, it is ready now.
GetWorldTimerManager().GetTimerElapsed(**this**, &AUTWeapon::RefireCheckTimer);

The sum of the elapsed and remaining time for a timer should be equal to the rate of the timer.

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Dismiss