简体   繁体   English

当弹丸击中两个“怪物”时,didBeginContact方法崩溃。 我知道为什么,但我不知道如何避免

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

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. 发生这种情况时-didBeginContact方法崩溃,表示secondBody为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. 第一次运行后-如果将bodyA作为射弹,将bodyB作为怪物-将它们传递给projectileDidCollideWithMonster ,并将它们都删除。 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: 在类的顶部添加了array和一个触发器:

    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:)
    }

}

Instead of removing your projectile immediately, just mark it for removal (eg 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 (eg at the end of this frame), go through and remove all projectiles marked for removal. 然后,在下一次物理检查之前(例如,在此帧末尾),检查并清除所有标记为要移除的射弹。

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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我不知道为什么这个表视图代码崩溃了 - i don't know why this table view code crashes 我的应用由于高度限制而崩溃,我不知道如何解决 - My App crashes because of the heightConstraints I don't know how to fix it 我在 SwiftUI 中找到了两种管理视图的方法,但我不知道有什么区别,也不知道哪种方法更好 - I found two ways to manage views in SwiftUI, but I don't know what the difference is and I don't know which is the better way 我不知道为什么结果不是我想的 - I don't know why the result is not my have thought 我不知道为什么在swift3中没有调用viewForHeaderInSection - I don't know why viewForHeaderInSection is not called in swift3 iOS组件会自动调整大小,但我不知道在哪里以及为什么 - iOS Component is automatically resizing but I don't know where and why 当我不知道会有多少节时,如何重新加载UITableView的数据? - How do I reload a UITableView's data when I don't know how many sections there will be? 当我不知道数组中有哪些对象时,是否为循环? - For loop when I don't know what objects are in an array? 我不知道为什么我的 Tableview 在选择行时没有推送 DetailView - I don't know why my Tableview did not push the DetailView when row is selected 我不知道如何将弹出框与按钮对齐 - I don't know how to align my popovers to button
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM