Managing Time Sensitive Events in Virtual Reality with Unreal Engine 4 1


One of the most challenging aspects of virtual reality (VR) development is meeting the spec requirements with our current level of hardware. VR is resource heavy and may affect the time driven events you are developing in your project. The reason for this is that there are three main ways (delay, game tick, and timer) to handle time in Unreal Engine 4 (UE4).

I have experience working with each of them in VR development, so I thought I would share what I have learned. In this post, my goal is to share with you which one I found to work the best for time critical events.


Delay

Delay is the simplest form of time management. You call the function or Blueprint node and then within the same scope of where the function was called pauses for a specified duration then resume.

Although the delay function is simple to use, it is also dangerous because the stall can affect other parts of your project. This can result in unwanted visuals that can cause simulation sickness.

Game Tick

Game tick is associated with the Event Tick Blueprint node or “Tick(float)” function in C++. This event happens every frame and the parameter the event get is the duration between the last frame tick. You can easily take advantage of this functionality by summing up the duration between frames until you reach a specific time.

Game tick is simple to use, but it does have its downsides. The timing will be a bit off because the in-between frame duration may not sum up to your specified time without going over by one tick. The in-between frame duration is GPU bound so on some PCs, the timing looks correct, but completely off on others.

Here is an example of using the Event Tick to toggle the visibility of a blueprint actor every 2 seconds:

blueprint actor for game tick time example

Blueprint actor with variables for toggling visibility

Event Tick to add time

Use event tick to add up time until 2 seconds then toggle visibility

Timer

A timer in UE4 points to a function or event address and calls the event after a specified time duration. You can use a timer in Blueprint through the nodes, “Set Timer by Event” or “Set Timer by Function Name”. The Blueprint timer nodes also let you set the timer to loop if you want it to. In C++, you will need to do the timer setup and looping yourself.

For any time critical events, a timer will give the most accurate result. This is because the function or event gets call the moment the timer expires. Another way to look at it is that the timers are CPU bound instead of GPU bound.

Here is an example using a timer to toggle the visibility of an actor in Blueprint and C++ (using the same block actor in Game Tick example):

timer to toggle visibility

Using timer to call toggle visibility function when time expires

toggle visibility function

Toggle visibility function

Block.h

#pragma once

#include "GameFramework/Actor.h"
#include "Block.generated.h"

UCLASS()
class VRDEMO_API ABlock : public AActor
{
    GENERATED_BODY()
protected:
    FTimerHandle time_handler;
    float period = 2.0;
    bool is_hidden = false;
    bool keep_looping = true;
public: 
    // Sets default values for this actor's properties
    ABlock();

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
 
    // Called every frame
    virtual void Tick( float DeltaSeconds ) override;

    UFUNCTION()
        void toggleVisibility();
};

Block.cpp

#include "VRDemo.h"
#include "Block.h"

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

}

// Called when the game starts or when spawned
void ABlock::BeginPlay()
{
    Super::BeginPlay();
    UWorld* const world = GetWorld();
    if (world != NULL) {
        world->GetTimeManager().SetTimer(time_handler, this, &toggleVisibility, period);
    }
}

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

}

void ABlock::toggleVisibility()
{
    is_hidden = !is_hidden;
    this->SetActorHIddenInGame(is_hidden);

    if (keep_looping) {
        UWorld* const world = GetWorld();
        if (world != NULL) {
            world->GetTimeManager().SetTimer(time_handler, this, &toggleVisibility, period);
        }
    }
}

I hope you found this post helpful to you. If you found this post helpful, share it with others who may benefit from it.

If you have any questions or feel that I missed something important, feel free to leave a comment. To stay in touch, follow me on Twitter.

Additional Resources


About Steven To

Steven To is a software developer that specializes in mobile development with a background in computer engineering. Beyond his passion for software development, he also has an interest in Virtual Reality, Augmented Reality, Artificial Intelligence, Personal Development, and Personal Finance. If he is not writing software, then he is out learning something new.

One thought on “Managing Time Sensitive Events in Virtual Reality with Unreal Engine 4

Comments are closed.