2016-04-15 14 views
1

Ich bekomme den folgenden Fehler, wenn es einen Kontakt zwischen Geschoss und Flugzeug gibt.Unerwarteterweise gefunden Nil SKSpriteNode

fatal error: unexpectedly found nil while unwrapping an Optional value

Screenshot of error

Flugzeug Funktion:

func addPlane() { 
    var myplane : SKSpriteNode? 
    myplane = SKSpriteNode(imageNamed: "plane") 
    let actualY = random(min: 100, max: size.height - myplane!.size.height/2) 
    myplane!.position = CGPoint(x: size.width + myplane!.size.width/2, y: actualY) 
    myplane!.physicsBody = SKPhysicsBody(rectangleOfSize: myplane!.size) // 1 
    myplane!.physicsBody?.dynamic = false // 2 
    myplane!.physicsBody!.categoryBitMask = CollisionCategoryPowerUpOrbs 
    myplane!.physicsBody!.collisionBitMask = 0 
    myplane!.name = "plan" 
    addChild(myplane!)// 
    let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0)) 
    let actionMove = SKAction.moveTo(CGPoint(x: -myplane!.size.width/2, y: actualY), duration: NSTimeInterval(actualDuration)) 
    myplane!.runAction(SKAction.sequence([actionMove])) 

} 

Wenn der Benutzer den Bildschirm berührt, wird es eine Kugel mit diesem funciton schießen:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     guard let touch = touches.first else { 
      return 
     } 
     let touchLocation = touch.locationInNode(self) 
     var projectile : SKSpriteNode? 
     projectile = SKSpriteNode(imageNamed: "bomb") 
     projectile!.position = CGPoint(x: 50, y: 100.0) 
     projectile!.physicsBody = SKPhysicsBody(circleOfRadius: projectile!.size.width/2) 
     projectile!.physicsBody?.dynamic = true 
     projectile!.physicsBody!.allowsRotation = false 
     projectile!.physicsBody!.categoryBitMask = CollisionCategoryPlayer 
     projectile!.physicsBody!.contactTestBitMask = CollisionCategoryPowerUpOrbs 
     projectile!.physicsBody!.collisionBitMask = 0 
     projectile!.physicsBody!.linearDamping = 1.0 
     projectile!.name = "shot" 
     let offset = touchLocation - projectile!.position 
     if (offset.x < 0) { return } 
     addChild(projectile!) 
     let direction = offset.normalized() 
     let shootAmount = direction * 1000 
     let realDest = shootAmount + projectile!.position 
     let actionMove = SKAction.moveTo(realDest, duration: 2.0) 
     let actionMoveDone = SKAction.removeFromParent() 
     projectile!.runAction(SKAction.sequence([actionMove, actionMoveDone])) 
} 

Funktion, das Flugzeug zu verstecken bei Kontakt:

func didBeginContact(contact: SKPhysicsContact) { 
    let nodeB = contact.bodyA.node! 
    if nodeB.name == "plan" { 
     nodeB.removeFromParent() 
    } 
} 

Ich nenne die addPlane Funktion in ViewDidLoad wie folgt aus:

runAction(SKAction.repeatActionForever(
    SKAction.sequence([ 
     SKAction.runBlock(addPlane), 
     SKAction.waitForDuration(1.5) 
    ]) 
)) 
+3

Sie haben einen Physikkörper, an den kein Knoten angeschlossen ist, deshalb scheitern Sie am Knoten! Auspacken – Knight0fDragon

+2

Warum definieren Sie 'Myplane' und' Projektile' als Optionals? Sie geben ihnen unmittelbar danach Werte und gehen dann zu den Einstreukräften durch Ihren Code über. Definieren Sie sie einfach als nicht optional und vermeiden Sie, dass sich die Kraft wie die Pest ausbreitet. – Hamish

+1

Verwenden Sie 'if let' oder' guard let' bei 'SKSpriteNode (imageNamed:" bomb ")', so können Sie sich schützen und sicherstellen, dass das Sprite korrekt geladen wird. Z.B. 'guard let projectile = SKSpriteNode (imageNamed:" bombe ") else {print (" error ")}' – Knight0fDragon

Antwort

1

Ändern Sie Code mit einem '?' zu tun, um einen Null-Check:

func didBeginContact(contact: SKPhysicsContact) { 

    let nodeB = contact.bodyA.node 
    if nodeB?.name == "plan" {  
    nodeB?.removeFromParent() 
    } 
} 

Diese Lösung des Absturz verhindert hat aber den Nachteil, dass einige unnötigen Kontaktereignisse noch ausgelöst werden.

Das Entfernen eines Knotens innerhalb von didBeginContact sollte vermieden werden. Dies kann zu Situationen führen, in denen der Knoten bereits entfernt ist (nil), aber der PhysicsBody noch aktiv ist. (siehe auch die Kommentare von KnightOfDragon)

+2

Das löst das Problem nicht, maskiert es einfach – Knight0fDragon

+0

A hatte manchmal das gleiche Problem, dass ein Kontaktkörper keinen Knoten hat. Das passiert besonders, wenn mehrere Objekte auf dem Bildschirm sind und mehrere Kollisionen gleichzeitig passieren. Und natürlich habe ich überprüft, dass ich keine Physikkörper ohne Knoten erstellt habe. Die Nullkontrolle hat mein Problem gelöst, weil die nächste Kollision sofort mit der Null gefunden wurde. Nicht sicher, ob das ein SpriteKit Bug ist? – Stefan

+0

Sie erhalten wahrscheinlich eine Null, weil Sie das Sprite töten, ohne sicherzustellen, dass der Physikkörper damit stirbt. Sie entfernen nicht in der Update-Phase, überschreiben Sie die Update-Ende-Funktion und entfernen Sie alle Knoten an diesem Punkt – Knight0fDragon

Verwandte Themen