战斗时出现子弹无法销毁的bug
攻击时有概率无法销毁子弹,原因是表现层丢失了对于子弹的预制体控制,导致该预制体无法通过代码进行控制。产生这种现象的原因是:之前为了提高游戏的流畅度将子弹的表现层脚本改为使用对象池控制,而该脚本本身有一个创建预制体的行为,该申请预制体的行为并不是和战斗逻辑走的一个生命周期。这就导致了一个问题,就是预制体资源申请行为的完成时间无法确定,而我们游戏本身是对时间非常敏感的,往往几帧一个子弹就可能走完了全部逻辑被销毁。之前子弹被销毁时是直接将表现层的脚本一并销毁了,这样的话即使创建预制体的回调在子弹销毁后才调用,由于引用已经消失,也不会执行相关的操作。但是改成对象池后就出现一个问题,虽然理论上我们销毁了表现层的脚本,实际上它的引用还是有效的,所以相关的回调还是能够继续执行。之前就有考虑到在进行预制体初始化时对子弹是否存活进行判断,所以在实例化时会停止执行已经被标记为销毁的子弹的回调。但是还有一种情况,就是该回调在执行的时候,原有的表现层脚本已经从取用->回收->取用,即回调执行时该脚本已经再一次从对象池中被取出来使用了,显然该脚本肯定没有被标记为销毁,这使得回调顺利执行,但是新的事件也已经被调用,等新的回调执行完毕后,会将原来的指向旧预制体的变量指向新的预制体,这就导致了丢失了对旧的预制体的控制,从而产生了子弹无法销毁的情况。
解决方案:由于回调无法判断执行时的对象是否正确,采用的方案是让相应对象来控制回调是否执行。在申请预制体资源的类中,为每一个申请事件添加一个全局唯一id,让相应的对象在申请时获取并储存这个id,在该对象被销毁时,告知申请资源的类它所持有的事件均不要再执行,然后在执行回调的时候,判断该事件是否已经被标记为不执行,如果被标记了,则直接停止回调的执行。