我目前正在为iPhone编写游戏编码,我有时会因标题中的错误而随机崩溃。
我研究了很多,可能与泄漏(?)内存问题有关。我问过的人告诉我,这可能与添加一个零对象有关。我设置了异常断点和NSZombies,但是这些都没有识别崩溃,也没有给我发生崩溃的确切代码行。
经过一些碰撞测试后,我注意到,当touchesBegan方法或didBeganContact方法处于活动状态时,大部分时间都会发生。
这里是touchesBegan方法和didBeginContact方法的代码:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (touchEnabled == YES){
firstTouch++;
if (firstTouch == 1){
SKAction* removeFade = [SKAction removeFromParent];
SKAction* startFade = [SKAction fadeAlphaTo:0 duration:0.5];
SKAction* fadeSeq = [SKAction sequence:@[startFade, removeFade]];
[startScreen runAction:fadeSeq completion:^{
startScreenRemoved = YES;
[self gameCountdown];
touchToShoot = YES;
}];
}
if (firstTouch == 2){
weaponActivated = YES;
}
if (gameOver == YES){
[self removeAllActions];
[self removeAllChildren];
[bgPlayer stop];
touchToShoot = NO;
SKScene* gameScene = [[GameScene alloc] initWithSize:self.size];
SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:1];
[self.view presentScene:gameScene transition:doors];
gameOver = NO;
}
}
if (touchToShoot == YES) {
[self weaponParticle];
touchToShoot = NO;
[self performSelector:@selector(enableTouchToShoot) withObject:nil afterDelay:0.3]; //-enableTouchToShoot{} = touchToShoot = YES;
}
//Pause Button
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:@"pauseButton"]) {
[self pauseMenu];
}
else if ([node.name isEqualToString:@"continue"]) {
self.paused = NO;
pauseBG.hidden = YES;
pauseText.hidden = YES;
backm.hidden = YES;
cont.hidden = YES;
//Damit unsichtbare Buttons nicht während dem Spiel gedrückt werden
backm.zPosition = -100;
cont.zPosition = -100;
}
else if ([node.name isEqualToString:@"backtomenu"]) {
self.paused = NO;
[self displayAlert];
}
}
-(void)didBeginContact:(SKPhysicsContact *)contact{
if (contact.bodyA.categoryBitMask == shipCategory) {
//Explosion Animation
SKAction* wait =[SKAction waitForDuration:0.5];
SKAction* fadeOut = [SKAction scaleTo:0.0 duration:1];
remove = [SKAction removeFromParent];
explodeSequenceGO =[SKAction sequence:@[fadeOut,wait,remove]];
ExplosionPath = [[NSBundle mainBundle] pathForResource:@"Explosion" ofType:@"sks"];
Explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:ExplosionPath];
Explosion.position = CGPointMake(contact.bodyA.node.position.x, contact.bodyA.node.position.y);
[self addChild:Explosion];
[Explosion runAction:explodeSequenceGO];
[contact.bodyA.node removeFromParent];
[contact.bodyB.node removeFromParent];
[shipSmoke removeFromParent];
[player1 removeFromParent];
touchEnabled = NO;
[self gameOver];
}
if (contact.bodyA.categoryBitMask == enemyCategory || contact.bodyB.categoryBitMask == enemyCategory) {
//Explosion Animation
SKAction* wait =[SKAction waitForDuration:0.5];
SKAction* fadeOut = [SKAction scaleTo:0.0 duration:1];
remove = [SKAction removeFromParent];
explodeSequenceGO =[SKAction sequence:@[fadeOut,wait,remove]];
ExplosionPath = [[NSBundle mainBundle] pathForResource:@"Explosion" ofType:@"sks"];
Explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:ExplosionPath];
Explosion.position = CGPointMake(contact.bodyA.node.position.x, contact.bodyA.node.position.y);
[Explosion runAction:explodeSequenceGO];
[self addChild:Explosion];
[contact.bodyA.node removeFromParent];
[contact.bodyB.node removeFromParent];
hitCount++;
[self scoreChange:100];
}
if (hitCount>39) {
[self eLevel2];
}
}
有人看到错吗?我非常感谢任何提示,因为我几周都在寻找这个bug ....
编辑:崩溃只指向"主要"功能,根本没有帮助
并且在每个线程"动作"它只是指向Assembly(?)代码:
就像我说的那样,我试图通过各种调试工具(NSZombies,MemoryTool,Exceptional Breakouts等)来分析崩溃,但是没有一个给我有用的信息。当应用程序崩溃时,调试工具就会停止录制,但是他们不会向我显示任何错误或崩溃结果。
答案 0 :(得分:2)
我知道这已经有几个月了,但是当我从一个场景转换到另一个场景时,我也遇到了EXC_BAD_ACCESS错误。阅读了多篇文章,并在我的游戏中几乎每行代码都进行了评论,为我修复的是从方法返回之前从现有场景中删除所有对象,并且错误消失了。
- (void)returnToMenuScene {
SKTransition *reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0];
MenuScene *menuScene = [MenuScene sceneWithSize:self.scene.size];
[self.scene.view presentScene:menuScene transition:reveal];
[self.gameScene removeAllChildren];
return;
}
- (GameScene *)gameScene {
return (GameScene *)self.scene;
}
我希望将来可以帮助其他人
答案 1 :(得分:1)
我早期发现的一件事是,如果原始场景被SpriteKit过早杀死,场景之间的转换会导致崩溃。 - 我知道疯狂的谈话。
为了帮助我,我创建了一个基类场景,其中包括一个清理操作。
-(void)cleanUp
{
[self cleanUpChildrenAndRemove:self];
}
- (void)cleanUpChildrenAndRemove:(SKNode*)node {
for (SKNode* child in node.children) {
[self cleanUpChildrenAndRemove:child];
}
[node removeFromParent];
}
然后当我转换场景时,我让旧场景生存一段时间然后再摧毁它。 请注意在旧场景上使用操作以便稍后清理自己。 叫我偏执,妄想,但它修复了我的崩溃。当我在应用程序上收到Terminate事件时,我还需要调用清理。
if( oldscene!=nil )
{
SKTransition* doors = [SKTransition doorsOpenVerticalWithDuration:1.5];
doors.pausesIncomingScene = NO;
[[self view] presentScene:newscene transition:doors];
SKNode* dummynode = [SKNode node];
// wait for the transition to complete before we give up the referene to oldscene
[dummynode runAction:[SKAction waitForDuration:2.0] completion:^{
if ([oldscene isKindOfClass:[MyBaseScene class]])
{
// failing to clean up nodes can result in crashes... nice.
[((MyBaseScene*)oldscene) cleanUp];
}}];
[oldscene addChild:dummynode];
}
else
{
[[self view] presentScene:newscene];
}