setitimer 创建两个定时器_UE4 Timer(定时器)相关源码分析
前言
- 文章屬于舊有文章搬運, 之前在csdn上面
- 2019.11.6修改
Timer是定時器, 用途:
- 延時執行事件
- 周期性執行事件
Timer可以...
Timer能...
Timer...
...
編不下去了, 自己百度谷歌吧(手動狗頭)
TimerManager
Timer的管理類是FTimerManager, 是一個全局的Timer管理類.
通常通過UWorld::GetTimerManager()獲得
可以看到實際實現是先判斷GameInstance是否存在, 存在返回UGameInstance的TimerManger, 否則返回UWorld自己的TimerManger
接著, 如上圖, TimerManger在UWorld和UGameInstance的構造函數中創建, 調用構造函數, 不試圖賦值UGameInstance
在TimerManger的構造函數中, 主要還是給InternalTime設0, 該值是TimerManger內部的一個獨立時鐘, 在TimerManger的每次Tick調用時計時.
在UWorld::Tick中調用FTimerManager的Tick函數實際執行Timer里面的操作
TimerManger的銷毀是在UWorld::FinishDestroy和UGameInstance::FinishDestroy中
delete然后置nullptr, 簡單粗暴.
Timer的執行
從堆棧中也可以FTimerManger::Tick被UWorld::Tick調用
如圖, 這個函數體主要做了如下內容 :
- 先調用FTimerManager::HasBeenTickedThisFrame, 并維護LastTickedFrame避免一幀內被多次執行.
- 然后InternalTime計時, 增加DeltaTime偏移量
- 接著對ActiveTimerHeap和PendingTimerSet進行一定邏輯處理
ActiveTimerHeap是一個當前活躍的, 待處理的FTimerHandle數組
看while循環體主體邏輯:
不斷取堆頂的FTimerHandle, 并得到對應的FTimerData.
如果該FTimerData的狀態是可被移除, 那么移除, 繼續
不斷執行, 直到InternalTimer(內部的獨立時鐘)大于FTimerData的ExpireTime, 即定時器到時間了, 那么執行一定邏輯, 否則, 沒有過時間, 就直接break跳出循環
因為ActiveTimerHeap是按照過期時間排序的
接著看, 如果定時器到時間了, 會將ActiveTimerHeap的堆頂元素移動置CurrentlyExecutingTimer(當前正在執行的Timer), 并更新FTimerData的Status為ETimerStatus::Executing
注意, 這里的CurrentlyExecutingTimer和上文中的TopHandler是同一個值, 所以改Top(FTImerData)修改的是同一Timer的信息
然后, 重點來了
劃重點了!
劃重點了!
劃重點了!
上圖圈起來的代碼, CallCount(執行次數), 為了避免在兩幀之間時間過長而導致丟掉一些定時器的間隔執行, 計算, 兩幀之間實際需要執行多少次.
設一個Timer, 每0.1秒執行一次, Tick總共過了5秒, 有
- 定時器必定執行50次, 執行次數恒定
- 如果比較卡頓, 每0.5秒執行1幀, 即定時器可能也可以在同一幀執行多次
- 定時器是假定時, 即期望0.1s, 0.2s, 0.3s, 0.4s, 0.5s執行, 實際可能是0.5s, 0.5s, 0.5s, 0.5s, 0.5s執行5次
而Timer的執行, 實際上也就是綁定的代理執行. 此處略
// 可以參考代理相關的文章自己啃, 難度不大在執行后有個更新指針的操作, 為了防止執行后無效, 這是為什么呢?
考驗你C++功底的時候到了, 自行理解, 此處忽略(手動狗頭)
在Timer執行完畢之后, 做清理.
如果Timer不循環, 執行一次, 那么完成使命了, 清理掉吧!
如果Timer代理無效了, 那么無法完成使命, 也清理掉吧!
否則, 嗯, 設置下次時間, 打回去, 接著干活(手動狗頭)
// 所以循環Timer啊, Timer對應的代理實際對象啊, 多數是不需要人工維護移除的 // 即多數Timer綁定好, 不清除, 也沒啥影響, 他會自動移除無效的Timer最后再看PendingTimerSet的處理, 這是在當前Tick幀添加的定時器集合, 將里面的定時器添加到ActiveTimerHeap里面
即很明顯, Timer最少也會延遲一幀調用
Timer的使用
參照上面若干函數, 最后都通過FTimerManger::InternalSetTimer函數SetTimerForNextTick相關基本同, 略
FTimerManger::InternalSetTimer中在設置Timer時, 會查找一下TimerHandle是否有效, 有效會清除.
接著就是創建一個FTimerData信息, 并維護, 具體略了
最后貼一張使用圖, 一些基礎知識就懶得提了.
// 基礎知識 : TimerHandler清除, 獲得剩余時間, 暫停和取消暫停, 是否存在等函數 // 看看頭文件, 配合使用即可.以及提一下這兩個Timer的代理:
- DECLARE_DELEGATE(FTimerDelegate)
- DECLARE_DYNAMIC_DELEGATE(FTimerDynamicDelegate)
自行參考代理相關文章, 配合使用, 能玩出花(笑)
結語
- 騙贊, 騙評論了.
總結
以上是生活随笔為你收集整理的setitimer 创建两个定时器_UE4 Timer(定时器)相关源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 登泰山记翻译及原文
- 下一篇: 正能量的团队名字,最有凝聚力的团队名字4