前言
起因是作者制作了获取任务奖励后的提示列表,期望是这些“提示”可以延迟n秒后逐一消失。
具体实现是用一个事件,调用一次生成一个“提示”,然后延迟n秒后自动销毁。
只可惜,理想很美好,现实很骨感。
实际情况是:延迟节点后的清除控件动作只会执行一次。
也就是说,自动销毁的动作只会执行一次,很多控件都会遗留在屏幕上。
发现问题
在这个问题的驱使下,我进行了一些尝试。
最终归纳出这个事件示例:
示例1
在实际执行时,2s内快速点击五次,“Hello”打印了5次,说明触发了五次这个事件。
但是,“world”只打印了一次,说明这个期间,delay节点与后面的内容只生效了一次,或者说,其他四次都被忽略了。
那么为什么呢?
探索问题
细看这个问题,会发现,示例1 这个事件,它执行多次,每次都能把“打印Hello”这个事情做完,但是因为“打印world”这个事情需要等2s后才能做,所以每次到达“delay”后,都在这个门口等待,等着等着就丢了。
那么,就产生了问题:
UE中的事件调用,是相互独立的吗?由结果来反过来看,似乎不像是每次调用都是独立的,它们之间似乎存在的一定的关联关系。
另外,如果UE的事件调用是独立的,有没可能,是延迟节点不独立?因为每次都是延迟节点这里出问题。
解决思路
1、原本想着去学习群问各路大佬,但是被打哈哈略过了.....
2、UE论坛翻找别人的帖子(搜索引擎根本找不到相关的内容,所以只能去论坛找)
帖子1:《Delay each custom event call by x seconds》
下图为机翻:
看来,也有人遇到和我一样的问题,而且问题主要还是集中在事件里使用了“等待一段事件后做某一件事”的操作。
但是,在这个贴子里,我并没有看到有谁进行了原因说明。
不过,有人提供了一个思路,那就是“每次调用事件时,都会对这个需要延迟执行的动作进行累计,然后逐一执行”(后面有相详细的蓝图)。这个思路,本质上来说,其实就是进行问题规避,并不能使我满足,于是我继续探索。
贴子2:《Delay node only runs the first time custom event is called, never runs again》
下图为机翻:
这位提问者遇到的问题和我遇到的问题也有异曲同工之妙,但是我仍旧未从这篇问答帖中获取我想要的答案。
不过,因为这位提问者的蓝图里,涉及了循环中延迟的操作,这带来了一个新的问题方向——“要怎么实现带延迟的循环呢?”(以后再说...)
3、其实从一开始思考的时候,我就有去翻阅UE官方关于事件、延迟节点的说明文档了,但是文档更多的是讲解怎么用,并未提及说实际的执行逻辑,所以然并软。
我也有尝试看源码,但是...因为目前是先接触蓝图项目,尚未涉猎C++源码,所以功力有限,实在是没看出啥东西。
4、于是我写了一篇帖子,发在了UE论坛上,期望可以获得解答。
帖子:《The event is called repeatedly, and the delay node takes effect only once》
最后,得到的是这样的答案。
① 每次调用事件,它将重新执行事件中的内容。
放到这些带延迟的问题中,都成立。每次都是执行到延迟节点,然后因为被再次调用,所以延迟节点与后面的内容直接就失效了。
这意味着,再次调用时,若上一次事件调用的内容未执行完毕,则也会直接结束,重新开始。
② 规避问题思路
来自帖子的回复
本质上其实就是记下会被忽略的要做的事情,在背后一次一次慢慢做完(如前文帖子1中提及的方式)。
总结
由此,在UE中使用蓝图的话值得注意:
若是一个事件执行完毕需要的时间较长(例如里面有带延迟节点),那么,就需要小心外部会不会在它执行完毕前再次调用。若不可避免,则需要测试看看结果是否在期望范围内。
(不过,解答我问题的大佬也有说,事件里通常可以挂载很多内容,一般执行的速度够快,不足以引发问题。但是涉及这种延迟等没招的处理时,就不一样了,会出问题。)
附
写这篇专栏的时候,作者还只是一个初学者,内容也是在实现一些功能时摸索出来的,所以如果有理解不到位的地方,或者误人子弟的地方,希望能抛砖引玉,诸位大佬可以不吝赐教!!!我看到也会随之修正文章内容。