查看: 2014|回复: 2

[讨论] 关于Destroy销毁延迟和玄学Overlap(碰撞延迟)

[复制链接]

56

主题

407

回帖

8

精华

版主

☯ 博 丽 不 是 灵 梦 ☯

经验
6090
硬币
1024 枚

赞助用户永吧十五周年建吧日纪念勋章永吧十五周年倒计时海报勋章

发表于 2022-2-1 13:51:14 | 显示全部楼层 |阅读模式
本帖最后由 电童·Isamo 于 2022-2-20 12:22 编辑

众所周知,CTF有特别多的尿性,今天我就想跟大家分享一下其中几个比较反人类逻辑的尿性
在讲之前需要大家先学习:
1.CTF的事件执行顺序是:在一个游戏帧(MF默认50帧/s,即一帧为1/50秒【0.02秒】)按照大事件顺序(默认是全局事件——场景事件【主事件】——对象行为)执行一遍所有小事件,而对象行为又按照对象的实例(即对象在游戏里的表现体)被创建(注:如无特殊说明,以下【创建】均指含create的要素)的顺序或在编辑器里被摆放的顺序由新到旧执行的。不管是全局事件、场景主事件还是对象的行为内的事件,都是每一个游戏帧内从第一行开始,从上往下执行一遍
2.CTF执行完毕一轮事件后,绘制图像,然后进入下一轮事件执行,如此循环

                               
登录/注册后可看大图
一、Destroy销毁延迟
我们来看下面这个例子:

                               
登录/注册后可看大图

如果按照我们上面所讲的,假设destroy的尿性不存在,红块先赋值1,然后红块销毁,以我们大部分人的逻辑都会认为:红块销毁了,其数据理应也一并清空,那么结果应该是下面的变量判定不成功,绿块不会被销毁
然而真实的情况是:红块和绿块都被销毁了
这不是因为对象出bug了,而是CTF的一个尿性:Destroy在销毁一个对象A后,对象A的数据仍会在这一游戏帧内保留,可被调用、操作,待下一帧开始时,对象A的所有数据均被清空
所以我们上图的结果也就解释的通了:因为这三条事件是在同一游戏帧内执行的,所以在对象A被销毁后,其数据在这一游戏帧内仍然存在,可读可写,那么自然就会参与判定,即第三行的变量条件也就理应判定成功,绿块就会被一并销毁
那么怎么避免这个问题呢?这里我提供两种方案,供大家参考:
1.把第三行的事件拉到第一行的事件上方,使原第三行的事件变为第一行而先于赋值条件执行,因为第一帧判定不成功,所以就会跳过执行销毁绿块的事件,然后给红块赋值、销毁,进入第二游戏帧,此时红块的数据就已经被销毁了,再去调用红块的数值去判定就毫无意义了,绿块也就不会被销毁了。
2.第三行值改为2(或者别的值都行,只要不是1),第四行加一个:红块的对应数值+1(或者直接赋值为对应数值也行),原理同上
解决原理就是:延迟红块的判定,先比较后赋值最后销毁,让游戏帧去把红块的数据消掉

二、碰撞延迟(玄学overlap)
这个问题,我跟版主dasasdhba经常谈,昨天晚上一躺到床上就有了灵感,然后就在刚刚(2022.2.1上午)做了个实验。
先来看下面这个栗子:

                               
登录/注册后可看大图

                               
登录/注册后可看大图

我们仍然按照讲第一个玄学尿性的思路来看这个问题,如左图,红色块最下方1像素的区域与绿色块最上方1像素的区域重合理论上满足overlap的触发条件。那么start of frame限制其只能在场景一开始就执行而且只能执行一次,我们就保证了这两行只能执行一次,且仅限第一个游戏帧执行,第二个游戏帧开始就不会再执行
那么,按照正常的逻辑,红绿两块都会往上移动1像素(图上写错了,不是+1是-1),此时其二者中间重合的部分理论上还是重合的,那么第二行的overlap理论上也应该是判定成功的,蓝块也理应变成紫块的
下面是实际结果:

                               
登录/注册后可看大图

欸,是不是很神奇?理论上蓝块应该变紫块的,但是为什么蓝块就没有变呢?
这是因为:CTF的碰撞条件(一般是overlap)存在延迟,当对象A移动后,对象A若位于overlap条件左边(我们称为主动侧),则对象A的碰撞数据会被立即刷新到移动后的位置;若位于条件右边(我们称为被动侧),则该对象的碰撞数据在本游戏帧内不会被刷新,待下一个游戏帧开始后才会刷新
所以上图的原理也就好理解了。
红块位于主动测,绿块位于被动侧,红块向上移动1像素了,此时红块的碰撞数据被刷新,然而绿块虽然理论上也向上移动了1像素,但是由于绿块位于被动侧,根据尿性,它的碰撞数据本游戏帧内不会刷新,那么实际上就是:红块的实际碰撞区域最下方1像素与绿块的实际碰撞区域最上方1像素没有重合,导致判定不成功,因而蓝色块没有变成紫色
那么,如果我将位移方向调成向下移动1像素,结果就正好相反了,仍然是红色块主动,绿色块被动,红色块实际碰撞区域向下移动了1像素,但是绿色块的实际碰撞区域在本游戏帧内并没有移动,也就是:红色块实际上与绿色块有2像素是重合的,即原先重合的加上红色块移动后重合的。
那么,怎么解决这个问题呢?
很遗憾,这个问题目前没有一个完美的解决方法,目前个人认为要想让overlap判定无误,最好就是:
1.确定谁先移动,谁后移动,绝对不可以认为二者同时移动!
2.让这个对象移动,然后紧接着与另一个后移动对象先判定重合,然后执行判定动作,最后再让后移动的对象移动


                               
登录/注册后可看大图

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

>❀ To the Best You ❀<

36

主题

720

回帖

13

精华

版主

经验
7341
硬币
1154 枚

赞助用户永吧十五周年建吧日纪念勋章永吧十五周年倒计时海报勋章第五届MW杯亚军对不起,小姐盲猜大王数字君X68数字君X68数字君X78

发表于 2022-2-1 16:06:47 | 显示全部楼层
简化版:CTF傻贲(

点评

确实如此(((  发表于 2022-2-1 18:02
Moonstruck Blossom
个人网站:dasasdhba.github.io
您需要登录后才可以回帖 登录 | 创建账户

本版积分规则