UE4中的时间管理
发表于2016-06-18
游戏逻辑中难免会遇到一些时间相关的功能需求,UE4也提供了一些时间相关的功能。
当前UE4版本4.11.1。
一、时间轴
TimeLine是方便的用于时间相关变量控制的地方,在蓝图编辑器中可以创建时间轴。
双击相关时间轴可以进入编辑模式。
Timeline的编辑与大部分的曲线编辑器类似,[官方文档]的描述也非常的详尽。大部分与时间变化有关的功能都可以使用Timeline来实现。
Timeline也可以与Interp系列函数配合来实现动态的值域调整。
在时间轴相关函数中,还有两个比较特殊的函数。
分别是SetPlayRate。
用于设置时间轴播放的速率,以及SetTimeLineLengthMode。
这个函数的功能似乎与官方的描述有些不同,只会影响到SetTimeLineLength的效果,而不会对实际播放产生影响。
不知道是设计如此还是文档描述上的问题。
查看Timeline.cpp中的源码可以看到LengthMode这个变量并没有在TickTimeline()函数中使用。
在整个引擎中只在Timeline本身的函数GetTimelineLength与SetTimelineLengthMode中被使用到。
引擎源码中的注释为
1 2 3 | /** Specified how the timeline determines its own length (e.g. specified length, last keyframe) */ UPROPERTY(NotReplicated) TEnumAsByte |
从这里看,应该是文档的描述方式有问题。这个变量是不会对播放模式进行影响的。
二、Matinee
对于关卡中的物体控制,UE4提供了一套更加方便的工具,那就是Matinee。
毕竟,如果要用Timeline来对物体进行控制,无论在实现还是管理上都非常的麻烦。
Matinee可以用于关卡中物品的移动控制,如电梯。也可以用于摄像头的控制来实现漫游展示,或者是过场动画。
Matinee的使用相当的简单明了,如果之前有使用过类似的动画制作软件的话,会很容易上手。
通过[官方文档]能快速上手,其中有不少例程可以作为参考。
三、速度控制
UE4中有一套自己的时间控制系统,可以实现类似于子弹时间、固有时制御的功能。
要对整个游戏时间的运行速率进行控制,可以使用SetGlobalTimeDilation。
设置的值在0.0001与20之间,超过范围会被Clamp。也就是说可以减慢10000倍或者加速20倍。
不建议加速太多,对运算效率的消耗非常大。玩家的配置不够时会出现问题。
另外有专门对Actor用的速度控制函数:
可以单独调整物体的时间速率。
四、定时器
Timer用于在中指定的时间上运行特定的任务,主要用于周期性执行任务,也可以实现类似于Delay的功能。
定时器的功能由一系列函数构成,使用起来非常直观。
在C++中也可以对Timer进行使用,所有继承自AActor的类都可以使用GetWorldTimerManager来进行定时器设定。
1 2 3 | FTimerHandle time_handler; GetWorldTimerManager().SetTimer(time_handler, FTimerDelegate::CreateSP( this , &SMusicList::DelayTest), 0.3f, false ); |
需要注意的是,对于有的类,直接这样使用是有风险的,需要判定一下世界是否存在。否则,在UWorld为空时会导致跳出。
1 | if (GetWorld()) GetWorld()->GetTimerManager().ClearAllTimersForObject( this ); |
五、Tick
Tick会在每帧都被调用,可以用于一些需要严格同步的功能。
在UE4中,Tick函数有TickGroup的概念,各个组中的Tick中每一帧中被调用的时机是不同的。
· TG_PrePhysics – 在物理模拟运行之前执行
· TG_StartPhysics – 用于开始物理引擎的特殊的Tick组
· TG_DuringPhysics – 与物理引擎并行执行的Tick组
· TG_EndPhysics – 用于结束物理模拟的特殊的Tick组
· TG_PostPhysics- 在刚体以及衣物的模拟结束后才会运行的Tick组
· TG_PostUpdateWork – 在帧内所有更新完成之后才会执行的Tick组
· TG_LastDemotable – 所有被延迟到最后执行的的Tick组
· TG_NewlySpawned – 特殊的Tick组,实际上并不是一个组,而是在所有的Tick组都运行完毕后,对所有世界中新生成的物体进行Tick
一般情况下Tick是隶属于TG_PrePhysics的,也有一些功能在其他的组中,例如粒子发射器就是运行在TG_PostUpdateWork组中的。Tick的调用通常来自UWorld实例的Tick函数。
Slate中的Tick是直接来源于SWidget中的Paint函数的,因此带有额外的参数。
通常tick的运行函数应该尽量的简单,否则有可能会导致游戏卡死。
在蓝图中,可以对蓝图类对应的TickGroup进行修改。
不是继承自AActor的类可能没有这个函数,因为他们可能并不属于TickGroup系统的管辖之下。控件蓝图由于是来自UUserWidget的,所以并没有这个函数。
六、总结
UE4中目前的时间相关函数基本够用,基本上需要的逻辑都能通过上面的几个类目中的功能实现。
时间相关的函数有时会难以调试,不过只要提前注意的话就不会有什么太大的问题,一般情况下。