定时器 可以设置在经过一段时间后以固定的时间间隔重复或单次执行某个操作。
定时器管理
定时器在全局 定时管理器(FTimerManager)中管理。全局定时管理器存在于 AActor(通过GetWorldTimerManager()获得)和 UWorld(通过GetTimerManager()获得)中。可以通过两个函数使用定时器管理器来设置定时器:SetTimer 和 SetTimerForNextTick,它们各自都有一些重载。最常用的一个定时器如下:
void SetTimer(FTimerHandle& InOutHandle,
UserClass* InObj,
typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod,
float InRate,
bool InbLoop = false,
float InFirstDelay = -1.f)
如果调用定时器的对象(如Actor)在时间结束前被销毁,则相关定时器会自动取消。在此情况下,定时器句柄将变为无效,并且不会调用该函数。
GetWorldTimerManager().SetTimer(TimeHandle, this, &ATestTimerActor::TimerCallback, 1.0, true, 3.0);
设置和清空定时器
要清空定时器,将SetTimer期间填充的FTimerHandle传递到FTimerManager函数ClearTimer中即可,定时器句柄将在此刻失效,并可以再次用于管理新定时器。使用现有定时器句柄调用SetTimer,将清空该定时器句柄引用的定时器,并将它换成新的定时器。此外,与特定对象关联的所有定时器都可以通过调用ClearAllTimersForObject来清空。
以小于等于0的速率调用SetTimer等效于调用ClearTimer。
GetWorldTimerManager().ClearTimer(TimeHandle);
暂停和恢复定时器
FTimerManager的函数 PauseTimer 可以暂停定时器,而 UnPauseTimer 可以恢复被暂停的定时器。
GetWorldTimerManager().PauseTimer(TimeHandle);
GetWorldTimerManager().UnPauseTimer(TimeHandle);
定时器状态
- 函数 IsTimerActive,用于确定指定定时器当前的状态,是否活跃且未暂停。
- 函数 IsTimerPaused,用于确定指定定时器当前是否处于暂停状态。
GetWorldTimerManager().IsTimerActive(TimeHandle);
GetWorldTimerManager().IsTimerPaused(TimeHandle);
定时器还有许多其他的函数。如:GetTimerRate获取定时器速率、GetTimerElapsed本次定时回调经过的时间、GetTimerRemaining本次定时回调剩余时间等。
测试代码
FTimerHandle TimeHandle;
void TimerCallback();
FTimerHandle TimeHandle1;
void TimerCallback1();
#include "TestTimerActor.h"
// Sets default values
ATestTimerActor::ATestTimerActor()
{
// 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;
TimerCount = 10;
}
// Called when the game starts or when spawned
void ATestTimerActor::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(TimeHandle, this, &ATestTimerActor::TimerCallback, 1.0, true, 3.0);
}
void ATestTimerActor::TimerCallback()
{
UE_LOG(LogClass, Log, TEXT("I'm Timer Callback!"));
--TimerCount;
if (TimerCount == 6)
{
GetWorldTimerManager().PauseTimer(TimeHandle);
UE_LOG(LogClass, Log, TEXT("Timer is Paused"));
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerPaused(TimeHandle) ? TEXT("Paused") : TEXT("Running"));
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerActive(TimeHandle) ? TEXT("Running") : TEXT("Paused"));
GetWorldTimerManager().SetTimer(TimeHandle1, this, &ATestTimerActor::TimerCallback1, 5.0, false);
}
else if (TimerCount <= 0)
{
GetWorldTimerManager().ClearTimer(TimeHandle);
UE_LOG(LogClass, Log, TEXT("Timer is cleard"));
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerPaused(TimeHandle) ? TEXT("Paused") : TEXT("Running"));
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerActive(TimeHandle) ? TEXT("Running") : TEXT("Paused"));
}
}
void ATestTimerActor::TimerCallback1()
{
GetWorldTimerManager().UnPauseTimer(TimeHandle);
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerPaused(TimeHandle) ? TEXT("Paused") : TEXT("Running"));
UE_LOG(LogClass, Log, TEXT("IsTimerPaused? %s"), GetWorldTimerManager().IsTimerActive(TimeHandle) ? TEXT("Running") : TEXT("Paused"));
}