Language:
Page Info
Skill Level:
Engine Version:
Share

Gameplay定时器

**定时器**安排在经过一定延迟或一段时间结束后要执行的操作。例如,您可能希望玩家在获取某个能力提升道具后变得无懈可击,然后10秒钟后恢复可受伤害状态。又或者,您可能希望玩家在穿过一间充满毒气的房间时,每秒受到一次伤害。上述每种情况都可以使用定时器来实现。

定时器管理

定时器在全局 定时器管理器FTimerManager类型)中管理。全局定时器管理器存在于 游戏实例 对象上以及每个 场景 中。有两个函数可以使用定时器管理器来设置定时器:SetTimerSetTimerForNextTick,它们各自都有一些重载。每个函数都可以连接到任意类型的对象或函数委托,SetTimer可以设为根据需要定期重复。请参阅定时器管理器API页面 以了解有关这两个函数的更多详细信息。

如果要对其调用定时器的对象(如Actor)在时间结束前被销毁,则相关定时器会自动取消。在此情况下,定时器句柄将变为无效,并且不会调用该函数。

要访问定时器管理器,可以使用AActor函数GetWorldTimerManager,它会在UWorld中调用GetTimerManager函数。要访问全局定时器管理器,使用UGameInstance函数`GetTimerManager'。如果场景因为任何原因而没有自己的定时器管理器,也可以退而求其次,使用全局定时器管理器。全局管理器可以用于与任何特定场景的存在没有相关性或依赖性的函数调用。

定时器可以与标准的C++函数指针、TFunction对象代理 一起使用。

设置和清空定时器

FTimerManagerSetTimer函数将定时器设置为在一段延迟后调用函数或委托,可以设置为不限次重复调用该函数。这些函数将填充 定时器句柄FTimerHandle类型),后者可用于暂停(和恢复)倒计时,查询或更改剩余时间,甚至可以取消定时器。可以在定时器调用的函数内部设置定时器,甚至可以重复使用用来调用这个函数的定时器句柄。一种用法是延迟依赖于尚未产生、但预计很快会产生的Actor的Actor的初始化;从属Actor初始化函数可以设置一个定时器,在经过固定时长(如一秒)后再次调用这个初始化函数。或者,该初始化函数可以由在成功时自动清空的循环定时器调用。

定时器还可以设置为在下一帧运行,而不是按固定间隔。实现方法是调用SetTimerForNextTick,但需要注意的是,该函数不填充定时器句柄。

要清空定时器,将SetTimer期间填充的FTimerHandle传递到FTimerManager函数ClearTimer中。定时器句柄将在此刻失效,并可以再次用于管理新定时器。使用现有定时器句柄调用SetTimer将清空该定时器句柄引用的定时器,并将它换成新定时器。

最后,与特定对象关联的所有定时器都可以通过调用ClearAllTimersForObject来清空。

示例:

void AMyActor::BeginPlay()
{
    Super::BeginPlay();
    // 从现在开始两秒后,每秒调用一次RepeatingFunction。
    GetWorldTimerManager().SetTimer(MemberTimerHandle, this, &AMyActor::RepeatingFunction, 1.0f, true, 2.0f);
}

void AMyActor::RepeatingFunction()
{
    // 调用该函数达到足够次数后,清空定时器。
    if (--RepeatingCallsRemaining <= 0)
    {
        GetWorldTimerManager().ClearTimer(MemberTimerHandle);
        // MemberTimerHandle现在可以复用于其他任意定时器。
    }
    // 在此进行一些操作...
}

以小于等于0的速率调用SetTimer等效于调用ClearTimer

暂停和恢复定时器

FTimerManager函数PauseTimer使用定时器句柄来暂停正在运行的定时器。这样可阻止定时器执行其函数调用,但经过的时间和剩余时间将保持暂停时的状态。UnPauseTimer使暂停的定时器恢复运行。

定时器信息

除了管理定时器,定时器管理器还提供了用于获取特定定时器信息的函数,如速率、经过的时间、剩余时间等。

定时器是否活跃

FTimerManagerIsTimerActive函数用于确定指定定时器当前是否活跃且未暂停。

示例:

// 这个武器是否正在等待再次射击?
GetWorldTimerManager().IsTimerActive(this, &AUTWeapon::RefireCheckTimer);

定时器速率

FTimerManager有一个函数GetTimerRate,它用于从定时器句柄获取定时器的当前速率(两次激活之间的时间)。定时器速率不能直接更改,但可以使用其定时器句柄调用SetTimer来清空定时器并创建新定时器,新定时器除了速率不同,其他保持不变。如果定时器句柄无效,则GetTimerRate将返回值-1

示例:

// 该武器的射击速率在预热时变化。当前是否正在等待射击,如果是,两次射击之间的当前间隔是多久?
GetWorldTimerManager().GetTimerRate(this, &AUTWeapon::RefireCheckTimer);

经过时间和剩余时间

FTimermanager通过GetTimerElapsedGetTimerRemaining,针对与所提供的定时器句柄关联的定时器,提供了返回经过时间和剩余时间的功能。与GetTimerRate一样,如果定时器句柄无效,则这两个函数将返回-1

示例:

// 该武器准备好再次射击之前将经过多长时间?如果答案为-1,则表示现在已准备就绪。
GetWorldTimerManager().GetTimerElapsed(this, &AUTWeapon::RefireCheckTimer);

定时器的经过时间和剩余时间之和应该等于定时器的速率。

已知问题

  • 该代码目前并非线程安全,如果从游戏线程外部访问可能会导致断言。

相关页面