囿里有条小咸鱼 发表于 2022-2-1 13:51:14

关于Destroy销毁延迟和玄学Overlap(碰撞延迟)

本帖最后由 电童·Isamo 于 2022-2-20 12:22 编辑

众所周知,CTF有特别多的尿性,今天我就想跟大家分享一下其中几个比较反人类逻辑的尿性
在讲之前需要大家先学习:
1.CTF的事件执行顺序是:在一个游戏帧(MF默认50帧/s,即一帧为1/50秒【0.02秒】)内先按照大事件顺序(默认是全局事件——场景事件【主事件】——对象行为)执行一遍所有小事件,而对象行为又按照对象的实例(即对象在游戏里的表现体)被创建(注:如无特殊说明,以下【创建】均指含create的要素)的顺序或在编辑器里被摆放的顺序由新到旧执行的。不管是全局事件、场景主事件还是对象的行为内的事件,都是每一个游戏帧内从第一行开始,从上往下执行一遍的
2.CTF执行完毕一轮事件后,绘制图像,然后进入下一轮事件执行,如此循环
static/image/hrline/4.gif一、Destroy销毁延迟
我们来看下面这个例子:
https://s4.ax1x.com/2022/02/01/HFaJu8.png
如果按照我们上面所讲的,假设destroy的尿性不存在,红块先赋值1,然后红块销毁,以我们大部分人的逻辑都会认为:红块销毁了,其数据理应也一并清空,那么结果应该是下面的变量判定不成功,绿块不会被销毁。
然而真实的情况是:红块和绿块都被销毁了。
这不是因为对象出bug了,而是CTF的一个尿性:Destroy在销毁一个对象A后,对象A的数据仍会在这一游戏帧内保留,可被调用、操作,待下一帧开始时,对象A的所有数据均被清空
所以我们上图的结果也就解释的通了:因为这三条事件是在同一游戏帧内执行的,所以在对象A被销毁后,其数据在这一游戏帧内仍然存在,可读可写,那么自然就会参与判定,即第三行的变量条件也就理应判定成功,绿块就会被一并销毁
那么怎么避免这个问题呢?这里我提供两种方案,供大家参考:
1.把第三行的事件拉到第一行的事件上方,使原第三行的事件变为第一行而先于赋值条件执行,因为第一帧判定不成功,所以就会跳过执行销毁绿块的事件,然后给红块赋值、销毁,进入第二游戏帧,此时红块的数据就已经被销毁了,再去调用红块的数值去判定就毫无意义了,绿块也就不会被销毁了。
2.第三行值改为2(或者别的值都行,只要不是1),第四行加一个:红块的对应数值+1(或者直接赋值为对应数值也行),原理同上
解决原理就是:延迟红块的判定,先比较后赋值最后销毁,让游戏帧去把红块的数据消掉。

二、碰撞延迟(玄学overlap)
这个问题,我跟版主dasasdhba经常谈,昨天晚上一躺到床上就有了灵感,然后就在刚刚(2022.2.1上午)做了个实验。
先来看下面这个栗子:
https://s4.ax1x.com/2022/02/01/HFwhX6.pnghttps://s4.ax1x.com/2022/02/01/HFwI0O.png
我们仍然按照讲第一个玄学尿性的思路来看这个问题,如左图,红色块最下方1像素的区域与绿色块最上方1像素的区域重合,理论上满足overlap的触发条件。那么start of frame限制其只能在场景一开始就执行而且只能执行一次,我们就保证了这两行只能执行一次,且仅限第一个游戏帧执行,第二个游戏帧开始就不会再执行。
那么,按照正常的逻辑,红绿两块都会往上移动1像素(图上写错了,不是+1是-1),此时其二者中间重合的部分理论上还是重合的,那么第二行的overlap理论上也应该是判定成功的,蓝块也理应变成紫块的
下面是实际结果:
https://s4.ax1x.com/2022/02/01/HF0TK0.png
欸,是不是很神奇?理论上蓝块应该变紫块的,但是为什么蓝块就没有变呢?
这是因为:CTF的碰撞条件(一般是overlap)存在延迟,当对象A移动后,对象A若位于overlap条件左边(我们称为主动侧),则对象A的碰撞数据会被立即刷新到移动后的位置;若位于条件右边(我们称为被动侧),则该对象的碰撞数据在本游戏帧内不会被刷新,待下一个游戏帧开始后才会刷新。
所以上图的原理也就好理解了。
红块位于主动测,绿块位于被动侧,红块向上移动1像素了,此时红块的碰撞数据被刷新,然而绿块虽然理论上也向上移动了1像素,但是由于绿块位于被动侧,根据尿性,它的碰撞数据本游戏帧内不会刷新,那么实际上就是:红块的实际碰撞区域最下方1像素与绿块的实际碰撞区域最上方1像素没有重合,导致判定不成功,因而蓝色块没有变成紫色
那么,如果我将位移方向调成向下移动1像素,结果就正好相反了,仍然是红色块主动,绿色块被动,红色块实际碰撞区域向下移动了1像素,但是绿色块的实际碰撞区域在本游戏帧内并没有移动,也就是:红色块实际上与绿色块有2像素是重合的,即原先重合的加上红色块移动后重合的。
那么,怎么解决这个问题呢?
很遗憾,这个问题目前没有一个完美的解决方法,目前个人认为要想让overlap判定无误,最好就是:
1.确定谁先移动,谁后移动,绝对不可以认为二者同时移动!
2.让这个对象移动,然后紧接着与另一个后移动对象先判定重合,然后执行判定动作,最后再让后移动的对象移动

static/image/hrline/4.gif
通过上述两个例子我们不难发现:CTF还是存在处理延迟的,说白了我个人猜测是CTF的GC,可能是处于性能考虑或者别的原因没有来得及清理,导致destroy延迟,亦或是其他逻辑顺序的问题导致overlap碰撞延迟,总之还是请大家小心编写这些事件!

dasasdhba 发表于 2022-2-1 16:06:47

简化版:CTF傻贲(
页: [1]
查看完整版本: 关于Destroy销毁延迟和玄学Overlap(碰撞延迟)