首先判断问题出现在Star的类方法doStickShorterWork中,于是逐步分词注释代码,最后剩下如下代码:
+(void)doStickShorterWork:(Stick *)stick{ GameScene *gameScene = [GameScene sharedGameScene]; CCPhysicsNode *physicsWorld = (CCPhysicsNode*)stick.parent; @synchronized(gameScene){ if ([stick.name isEqualToString:@"stickShorter"]) { return; } if ([stick.name isEqualToString:@"stickLonger"]) { Stick *stickNormal = [Stick stickNormal]; stickNormal.position = stick.position; [physicsWorld removeChild:stick cleanup:YES]; [physicsWorld addChild:stickNormal]; gameScene.stickInGameScene = stickNormal; return; } } CGPoint position = stick.position; __block Stick *stickShorter; @synchronized(gameScene){ stickShorter = [Stick stickShorter]; [physicsWorld removeChild:stick cleanup:YES]; stickShorter.position = position; [physicsWorld addChild:stickShorter]; gameScene.stickInGameScene = stickShorter; } }
省略掉了stick变短动画和恢复尺寸的代码,问题依旧.
在经过N次注释,编译,运行的Loop后,将问题逐渐锁定在stick没有正确删除上.遂再次推理涉及到可能删除与引用冲突的代码逻辑.
最后推断如果在五角星碰撞stick后,在碰撞回调中如果此时删除了stick会发生什么!?这肯定不是物理引擎愿意看到的情形:在物理对象的碰撞回调中,该物理对象竟然被删除了!这个显然不合常理,但在该App中是有可能发生的.
如果在Star类方法中stick删除代码调用时,碰撞回调方法还未返回,就会发生stick已经没有了,同时物理引擎还认为其存在的情况.
简单来说如果stick删除时,碰撞回调在运行就会出现僵尸对象,如果stick删除时,碰撞回调方法已经返回,则一切正常.这也符合僵尸对象随机出现的现象.