UE C++ Timer定时器的使用

[UE C++] Timer定时器

1. 要点:

  • UE的Timer包括了两个功能,延时和定时,通过bLoop来设置
  • Timer在 FTimerManager 中进行管理,FTimerManager 存在于UGameInstance实例中,每个场景物品都可以获取
  • 设置Timer有两个SetTimerSetTimerForNextTick两个接口
  • Timer通过一个 FTimerHandle 对象进行管理,包括暂停,恢复,取消等操作

2. FTimerManager

管理所有的Timer,存在于UGameInstance实例中,每个场景物品都可以获取,获取方法如下:

GetGameInstance()->GetTimerManager();
GetWorld()->GetTimerManager();
GetWorldTimerManager();

本质上都是通过UGameInstance::GetTimerManager()来获取

inline FTimerManager& GetTimerManager() const
{
    return (OwningGameInstance ? OwningGameInstance->GetTimerManager() : *TimerManager);
}
FTimerManager& AActor::GetWorldTimerManager() const
{
	return GetWorld()->GetTimerManager();
}

3. FTimerHandle

Timer的句柄,用于暂停,恢复,取消Timer,对Timer进行管理

3.1 声明

FTimerHandle TestTimerHandle;

3.2 暂停和恢复

GetWorldTimerManager().PauseTimer(TestTimerHandle);

GetWorldTimerManager().UnPauseTimer(TestTimerHandle);

3.3 Cancel

GetWorldTimerManager().ClearTimer(TestTimerHandle);

//取消指定对象的所有Timer
GetWorldTimerManagerr().ClearAllTimersForObject(this);

3.4 获取Timer状态

//Get Rate  TimerHandle无效返回-1
GetWorldTimerManager().GetTimerRate(TestTimerHandle);

//是否暂停
GetWorldTimerManager().IsTimerPaused(TestTimerHandle);

//是否活跃且未暂停
GetWorldTimerManager().IsTimerActive(TestTimerHandle);

//是否存在且等待运行
GetWorldTimerManager().IsTimerPending(TestTimerHandle);

//是否存在
GetWorldTimerManager().TimerExists(TestTimerHandle);

//剩余时间   TimerHandle无效返回-1
GetWorldTimerManager().GetTimerRemaining(TestTimerHandle);

//已运行时间 TimerHandle无效返回-1
GetWorldTimerManager().GetTimerElapsed(TestTimerHandle);

4. 设置Timer

4.1 SetTimer

有6个重载

//Callback 类的成员函数
void SetTimer
(
    FTimerHandle& InOutHandle, 
    UserClass* InObj,

    typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod,
    //typename FTimerDelegate::TUObjectMethodDelegate_Const< UserClass >::FMethodPtr 

    float InRate,
    bool InbLoop = false, 
    float InFirstDelay = -1.f
);

//Callback Delegate的Bind函数
void SetTimer
(
    FTimerHandle& InOutHandle, 

    FTimerDelegate const& InDelegate, 
    //FTimerDynamicDelegate const& InDynDelegate

    float InRate, 
    bool InbLoop, 
    float InFirstDelay = -1.f
);
DECLARE_DELEGATE(FTimerDelegate);//无法带参数
DECLARE_DYNAMIC_DELEGATE(FTimerDynamicDelegate);//无法带参数

//Callback空气,不知道有啥用
void SetTimer
(
    FTimerHandle& InOutHandle, 
    float InRate, 
    bool InbLoop, 
    float InFirstDelay = -1.f
);

//Callback TFunction,常用于Lambda函数(可捕获参数)
void SetTimer
(
    FTimerHandle& InOutHandle, 
    TFunction<void(void)>&& Callback, 
    float InRate, 
    bool InbLoop, 
    float InFirstDelay = -1.f 
);

笔者认为使用时可分为三类,下面举例说明:
首先定义一个测试函数

void ATimerHandleTest::TimerPrintTest()
{
	UE_LOG(LogTemp, Warning, TEXT("Timer Callback"));
}

类的成员函数

GetWorldTimerManager().SetTimer(TestTimerHandle, this, &ThisClass::TimerPrintTest, 2.0f, true);

Delegate

DECLARE_DELEGATE(FTestTimerHandle);

FTestTimerHandle TestTimerHandleDelegate;

TestTimerHandleDelegate.BindUObject(this, &ThisClass::TimerPrintTest);

GetWorldTimerManager().SetTimer(TestTimerHandle, TestTimerHandleDelegate, 2.0f, true);

TFunction

这里用Lambda函数举例

float t = 10.f;
GetWorldTimerManager().SetTimer(
    TestTimerHandle,
    [t] {
        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("Timer Callback:%f"), t));
    },
    2.f, true);

其他参数解释:

  • InRate: 循环速率,If <= 0.f, clears existing timers
  • InbLoop: 是否循环
  • InFirstDelay: 第一次触发的延时 If < 0.f InRate will be used.

4.2 SetTimerForNextTick

下一帧就会触发Callback,不是很常用,一共有5种重载,和SetTimer使用方法基本一致

FTimerHandle SetTimerForNextTick
(
    UserClass* inObj, 
    typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr inTimerMethod
    //typename FTimerDelegate::TUObjectMethodDelegate_Const< UserClass >::FMethodPtr inTimerMethod
);

FTimerHandle SetTimerForNextTick(FTimerDelegate const& InDelegate);

FTimerHandle SetTimerForNextTick(FTimerDynamicDelegate const& InDynDelegate);

FTimerHandle SetTimerForNextTick(TFunction<void(void)>&& Callback);

这里就不举例子了,和SetTimer基本相同

5. 注意事项

  • Timer是并非线程安全的,如果从游戏线程外访问可能会导致断言
  • 在UObject继承而来的UE4中的类创建Timer,当类的对象实例销毁时,Timer也会跟着销毁
  • 最好不要在函数定义局部的TimerHandle,虽然Timer会正常运行,但是程序员无法对Timer进行手动管理
  • 设置Timer时,如果已经为这个TimerHandle设置了Timer,它将替换旧的Timer
  • Timer速率不能直接更改,但可以使用其TimerHandle调用SetTimer来清空Timer并创建新Timer

参考链接

GamePlay 定时器

UE4随笔:Gameplay定时器

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于C语言中的定时器,可以使用SetTimer函数来设置。在C语言中,SetTimer函数可以定时执行一个回调函数。一个简单的示例代码如下: ``` // 定义回调函数 void timerCall(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { // 在这里写定时器触发后要执行的代码 } int main() { // 创建定时器 SetTimer(NULL, 0, 5000, timerCall); // 其他代码... return 0; } ``` 在这个示例中,使用SetTimer函数创建了一个定时器,它会每隔5000毫秒(即5秒)触发一次回调函数timerCall。在回调函数中,可以编写要执行的代码。需要注意的是,定时器的回调函数的参数类型是固定的,不能随意更改。 另外,需要包含相应的头文件和函数声明,具体的使用方式可以根据具体的C语言开发环境和需求进行调整。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++定时器](https://blog.csdn.net/Poo_Chai/article/details/130111116)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Timer定时器(C++)](https://blog.csdn.net/u011073673/article/details/52885682)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MustardJim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值