高级触发教程:帧计时

Ra2map:本文转载自【教程】高级触发教程:帧计时 - 红警任务之家

警告:本教程并不适合任务制作新手,最终达成的效果并不常用,且仅用于细枝末节的优化效果,只是非常特殊需求下的产物。因此,新手可以完全无视本教程中提及的所有细节。

我开发出这个触发组已经好几年了,也实际使用了几次,虽然说目前来看用处不大,但一直想写个教程分享一下,说不定什么时候就能派上用场吧。

帧计时

众所周知,YR中的触发条件“13 流逝时间…”仅能完成整数秒的延时。即使是触发条件“51 随机延时…”也不能随机出非整数秒,而是取整到最近的整数秒。

(注:本文中所有的“秒”都指的是游戏中超武倒计时/全局任务计时器的1秒,具体持续时间会随游戏速度的变化而变化,而非现实中的1秒。下同。)

而在游戏中,实际上最小的时间单位是“帧”。在每一帧中,引擎重新结算一次全部逻辑并重新绘制一次画面。任何在1帧之内发生的事件都被认为是同时发生的事情。1秒=15帧

也许你会注意到了,有时我们对”计时“这一需求并不满足精确到秒的精确度,比如在以下场景:

  • 需要制作在1秒之内先后发生的一系列事件(例:快速在不同位置播放一连串动画)
  • 需要制作一个发生时间不足1秒的事件(例:使用触发实现几帧的屏幕亮度变化,达到闪电划过的效果)
  • 需要对某个事件进行精确到帧的对齐(例:精确的踩点对上BGM、精确的控制字幕出现的时间)
  • 需要制作一个均匀的但是出现在非整数秒的一系列事件(例:5秒内均匀的执行3次)
  • 等等……

这个时候我们就无比期望有一个精确到帧的计时器。既然原版没有提供直接的方式,那我们有没有别的办法呢?这就是本教程要讲的主要内容。

这个计时器触发组,由三个功能部分组成:

  • 振荡器:一个每帧执行1次的触发。
  • 计数器:计算经过了多少帧。
  • 复位器:对整个计时器触发组进行复位。

首先是振荡器触发。什么样的触发能做到每帧都执行1次呢?根据帧的定义,既然1帧是游戏逻辑结算的最小单位,那么一个始终满足条件的重复触发就是1帧执行1次的。我习惯使用的条件是”13 流逝时间…“参数写0,当然”8 任何事件…“也是可用的。

如果不信的话,可以做如下试验:使用一个始终满足条件的重复触发,每次刷出1辆坦克,把这个触发允许1秒再禁止,你会发现无论在什么条件下执行,刷出坦克的数量总是精确的15辆。这也印证了以上的论断。

通常来说,出现了一个每帧都执行1次的触发被认为是触发制作中的错误,因为它可能会大量消耗计算资源,甚至导致某种形式的溢出(单位数量、小队实例)导致游戏极度变卡,但我们这里就是需要它……为此,我们也需要其它措施来严格的限制这个触发对资源的消耗,这个一会再谈。

既然有了一个每帧执行1次的触发,就可以通过统计这个触发执行的次数,来实现精确到帧的计时了。但是什么样的计数手段最好呢?一般来说我们需要这个计数手段可拓展、可重复,所以我通常会采取刷单位计数的方式。

就是让那个每一帧都执行一次的触发,每一次运行都在地图的不可见区域刷一个别的地方都用不到的单位,而我们的触发条件”60 科技类型存在…“参数可以用于计数,就可以在被刷出的单位数量到达一定数量的时候被触发。刷出了几个单位,就是经过了几帧,没问题。

为了让这个触发组可以复用,还需要在达到了一定的数量以后,清理掉所有的用于计数的单位。为所有的计数单位使用一个单独的作战方,使用将这个作战方直接全部摧毁是一个非常直接的方式。注意如果是重复利用已有单位进行计数,记得修改其ini,确保死亡武器、阵亡的嚎叫等都写上空白,否则使用触发组时可能听到地图外传来阵阵哀嚎或者爆炸声……

可以预想到的是,在振荡器触发执行的时候,游戏可能会产生轻微的卡顿。而实测的效果是卡顿几乎可以忽略。只要它不是一直在运行刷单位,而是只在需要的时候开启、经过短暂的计时以后被关闭、刷出来的单位被及时清理掉,这个触发组对游戏性能带来的影响就可以忽略。

总结一下这个触发组的组成:

  • 振荡器:重复,条件【流逝时间:0 / 任何事件】,结果【在地图的不可见区域刷出一个单位】
  • 计数器:条件【科技类型存在:计数单位到了一定数量】,结果【做你想做的事】
  • 复位器:条件【需要复位的时候使用】,结果【禁止振荡器,摧毁振荡器刷出的所有单位】

目前来看这个触发组的功能应该是无法替代的。至于用途,仅凭我贫乏的想象力,之前也就想到了那几种。也许还有更多用途,希望这篇教程能拓宽大家的思路。

帧对齐

这部分涉及到另一个需要以”帧“为单位精确计时的场景,与上面的帧计时关系不大,算是做一个补充。

我们在使用全局任务计时器的时候,有时需要达到”暂停计时器“的效果。通常使用的手段是”流逝时间1,计时延伸1“,即每秒把计时器加1秒,就和计时器自带的减1秒抵消了,达到计时器不动了的效果。

以上全都是理论中的想象。实际使用的时候可能会出现这样的问题:计时器的减1秒是从计时器开始倒计时每15帧减1秒,但是如果那个用来暂停计时器的触发是由玩家某个操作允许的,这个允许的时间节点并不一定落在计时器开始以后15帧的整数倍上。废话这么多,最终的后果就是计时器会在1秒之内先减1秒在加1秒,不停的在两秒之间跳动,俗称”跳秒“。虽然说影响不大,但看着数字乱跳就很烦……

我一开始以为这个需要使用帧计时器来解决,后来经过*@tslza* 的提醒,完全不用那么麻烦,可以这样简单的解决:

  • 触发A:流逝时间1,计时延伸1。
  • 触发B:流逝时间1,计时缩短1。

在计时开始的时候,同时允许触发A和触发B。需要暂停的时候,禁止触发B,恢复的时候再允许。

触发A和全局任务计时器本身一直保持着精确到帧的对齐。因为结算都在1帧之内,因此画面上不会有变化,数字也不会跳动了。然后用触发B来手动完成倒计时流逝。这就是一个完美的解决方案了。


竹蜻蜓:昨天与人讨论的时候,谈到有一个问题挺有意思的:短时间刷了这么多单位,为啥这个触发组实际用起来不会突然卡一下之类的?

我目前这样解释:刷出来的单位就是在原地不动的,不执行脚本也不搜索敌人……

寻仇和寻路可能才是刷大量单位的时候消耗计算量的大头,不寻仇也不寻路的话其实真的消耗没那么可怕……

比如说几十辆坦克叠在一个路径点上发呆,是没那么卡的;但你打它一下,这些坦克突然开始动了,游戏就会一瞬间变卡。

  • 高级触发教程:帧计时
  • 作者:竹蜻蜓(Heli)  发布于:2020-08-02  许可协议:若无特别说明,均为 CC BY-NC-SA
高级触发教程:字幕队列
XCC:提取 MIX 中的文件