UE4 Timer(定时器)相关源码分析
前言
- 这边文章有点迟, 咸鱼了一周, 想着这周快过去了, 所以翻代码补写的.
- 内容有一些, 但实际也没有啥, 没有深扒
- Timer的主要用处, 就是延时处理, 也玩不出啥花样来.
核心
- struct FTimerData
储存Timer信息的一个结构体 - struct FTimerUnifiedDelegate
存储Timer代理的一个结构体
class FTimerManager - Timer的管理类
正文
- TimerManager的位置
创建, 翻阅源码同时结合使用, 我们使用的Timer是UWorld::GetTimerManager()获得的
可以发现此处的GetTimerManager是找GameInstance是否存在, 存在返回GameInstance的TimerManager, 否则返回UWorld的TimerManager, 下面两张图是UWorld和GameInstance中分别创建TimerManager的地方
然后在UWorld里面查找TimerManager, 只发现在UWorld::FinishDestroy()时才有一行销毁代码
补 : 因为UWorld的代码在多个文件中, 写到后面发现UWorld的Tick在LevelTick.cpp中, 里面有TimerManager的Tick函数
GameInstance里面基本相同, 只有在UGameInstance::FinishDestroy()时才有一行销毁函数
- Timer的执行
从堆栈中可以看到是在UWorld中的Tick函数里面执行, 所以定时器执行的实际时间是大于等于InRate(延迟时间)的第一帧
核心函数是FTimerManager的Tick函数, 里面分别对ActiveTimerHeap和PendingTimerSet进行处理, 并维护一个LastTickedFrame和InternalTime两个时间值
这个InternalTime是一个独立于World的时钟
对ActiveTimerHeap(当前活跃的Timer堆)做处理, 先将等待移除的Timer移除
然后是到时间的Timer的执行, 可以看一下圈起来的代码,有一个执行次数, 为了避免在两帧之间时间过长而导致丢掉一些循环定时器的执行
接下来是对执行后的定时器进行处理, 如果是循环的且有效(代理存在或者不依赖代理), 则重新添加到堆里面, 否则移除
而PendingTimerSet的处理, 这是一个在当前Tick帧添加的定时器集合, 将里面的定时器添加到ActiveTimerHeap里面,
- Timer的使用
如图, 函数定义如下, 并最后通过InternalSetTimer()函数进行处理SetTimerForNextTick相关省略, 有兴趣自己去看
首先会查找一下已经TimerHandle是否存在, 存在则清除.
然后就是创建一个FTimerData信息, 并进行维护
Timer的内部机制不打算写教程, 懂得看一看就够了, 不懂的也不知道该怎么解释
本质上就是维护一个FTimerData的数据, Tick中进行Timer的执行和维护罢了.
再贴一张使用的时候的几种方式, 一些基础知识就懒得提了, 懒得写初级教程
基础知识 : TimerHandler清除, 获得剩余时间, 暂停和取消暂停, 是否存在等功能性函数, 看看头文件, 配合使用即可.
这里重点提一下两个代理, 下面是两个定义及位置
至于为什么提及呢, 配合DECLARE_DELEGATE这种代理, 可以实现一些骚操作, 例如绑的代理带参数啊, 下篇文章中会说一些代理相关的东西, 这里只先贴一张图.
结语
- 写的好像没啥用, 懒得写新手教程, 高级的又写不了, 就不上不下的乱贴源码了.
- 下一篇是代理了, 时间, 一周内吧…