When projectile hits two “monsters” the didBeginContact method crashes. I know why but i don't know how to avoid it

◇◆丶佛笑我妖孽 提交于 2019-12-08 13:43:00

问题


So I have this code from the tutorial:

func didBeginContact(contact: SKPhysicsContact) {

    // 1
    var firstBody: SKPhysicsBody?
    var secondBody: SKPhysicsBody?
    var body: SKPhysicsBody

    //contact.bodyB.node!.physicsBody!.allContactedBodies().count


        if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
            firstBody = contact.bodyA
            secondBody = contact.bodyB
            println("1 = A, 2 = B")
        } else {
            firstBody = contact.bodyB
            secondBody = contact.bodyA
            println("2 = A, 1 = B")
        }



        // 2
        if ((firstBody!.categoryBitMask & PhysicsCategory.Monster != 0) &&
            (secondBody!.categoryBitMask & PhysicsCategory.Projectile != 0)) {

                for var c = 1; c <= contact.bodyB.node!.physicsBody!.allContactedBodies().count; c++ {
                    projectileDidCollideWithMonster(firstBody!.node as! SKSpriteNode, monster: secondBody!.node as! SKSpriteNode)

                }
                secondBody!.node?.removeFromParent()
        }
}

func projectileDidCollideWithMonster(projectile:SKSpriteNode, monster:SKSpriteNode) {
    println("Hit")
    changeScore(1)
    changeAmo(true)
    projectile.removeFromParent()
    monster.removeFromParent()
}

Then what is happening is that a projectile sometimes hit TWO monsters at once.

When this happens - didBeginContact method crashes saying that secondBody is nil.

After a thorough research I found out the reason:

when projectile collides with two other nodes at once - this method runs two times. After the first run - if gets bodyA as projectile, bodyB as a monster - passes them on to projectileDidCollideWithMonster and it removes them both. then it runs immediately again but at that moment projectile doesn't exist anymore and it crashes not able to assign it's node.

I have no idea how to overcome this:( any suggestions, please?

SOLUTION: Thanks to ideas below i did some changes.

added and array and a trigger at the top of the class:

    var bodiesToBeRemoved = [SKSpriteNode]()
    var shouldRemoveBodies = false

and did these modifications:

 func projectileDidCollideWithMonster(projectile:SKSpriteNode, monster:SKSpriteNode) {
 /* Called when collisions is detected and collided nodes are passed to it */
    //score and stuff
    println("Hit")
    changeScore(1)
    changeAmo(true)

    //collect the nodes to be removed
    bodiesToBeRemoved.append(projectile)
    bodiesToBeRemoved.append(monster)

    //change the trigger to remove collected nodes later on
    shouldRemoveBodies=true

}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */

    //check the trigger
    if shouldRemoveBodies == true {
        println("\(bodiesToBeRemoved.count)")
        //remove collected nodes
        for var i = 0; i<bodiesToBeRemoved.count; i++ {
            bodiesToBeRemoved[i].removeFromParent()
        }

        //reset array
        bodiesToBeRemoved.removeAll(keepCapacity: false)

        //reset the trigger
        shouldRemoveBodies = false
    } else {
        //do nothing:)
    }

}

回答1:


Instead of removing your projectile immediately, just mark it for removal (e.g. by setting a boolean flag, or adding it to some collection if it's not already in the collection). Then later, before the next physics check (e.g. at the end of this frame), go through and remove all projectiles marked for removal.




回答2:


Just check it's nil or not better than check every nodes's mark.

func removeNodeFromPhysicsBody(ps: SKPhysicsBody){
    if (ps.node != nil){
        ps.node?.removeFromParent()
    }
}

func wallDidCollideWithMeteor(wall:SKPhysicsBody, meteor:SKPhysicsBody) {
    removeNodeFromPhysicsBody(wall)
    removeNodeFromPhysicsBody(meteor)
}


来源:https://stackoverflow.com/questions/31057866/when-projectile-hits-two-monsters-the-didbegincontact-method-crashes-i-know-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!