且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

iOS SpriteKit - 碰撞和联系人无法按预期工作

更新时间:2023-02-01 18:26:09

为了帮助诊断这些类型的问题,我编写了一个可以从任何地方调用的函数,它将分析当前场景并生成一个节点列表与其他人发生碰撞以及我的场景将收到哪些碰撞通知.

To help diagnose these types of problems, I have written a function that can be called from anywhere and which will analyse the current scene and produce a list of what nodes with collide with which others and which collisions my scene will be notified for.

该功能是独立的,不需要告诉任何有关场景中节点的信息.

The function is stand-alone and does not need to be told anything about the nodes in the scene.

函数如下:

            //MARK: - Analyse the collision/contact set up.
    func checkPhysics() {

        // Create an array of all the nodes with physicsBodies
        var physicsNodes = [SKNode]()

        //Get all physics bodies
        enumerateChildNodesWithName("//.") { node, _ in
            if let _ = node.physicsBody {
                physicsNodes.append(node)
            } else {
                print("(node.name) does not have a physics body so cannot collide or be involved in contacts.")
            }
        }

//For each node, check it's category against every other node's collion and contctTest bit mask
        for node in physicsNodes {
            let category = node.physicsBody!.categoryBitMask
            // Identify the node by its category if the name is blank
            let name = node.name != nil ? node.name : "Category (category)"
            let collisionMask = node.physicsBody!.collisionBitMask
            let contactMask = node.physicsBody!.contactTestBitMask

            // If all bits of the collisonmask set, just say it collides with everything.
            if collisionMask == UInt32.max {
                print("(name) collides with everything")
            }

            for otherNode in physicsNodes {
                if (node != otherNode) && (node.physicsBody?.dynamic == true) {
                    let otherCategory = otherNode.physicsBody!.categoryBitMask
                    // Identify the node by its category if the name is blank
                    let otherName = otherNode.name != nil ? otherNode.name : "Category (otherCategory)"

                    // If the collisonmask and category match, they will collide
                    if ((collisionMask & otherCategory) != 0) && (collisionMask != UInt32.max) {
                        print("(name) collides with (otherName)")
                    }
                    // If the contactMAsk and category match, they will contact
                    if (contactMask & otherCategory) != 0 {print("(name) notifies when contacting (otherName)")}
                }
            }
        }  
    }

你还需要检查这三件事:

You also need to check these 3 things:

  1. 场景必须SKPhysicsContactDelegate
  2. 您必须设置 physicsWorld.contactDelegate = self
  3. 您需要实现以下可选方法之一SKPhysicsContactDelegate:

didBeginContact

didBeginContact

didEndcontact

didEndcontact

设置完所有图片后,应调用该函数 - 通常在 didMoveToView 工作结束时:

The function should be called once you have set up all of your pics - usually at the end of didMoveToView works:

checkPhysics()

当我在我的实践 Swift 项目中从 didMoveToView 的末尾调用此函数时,我得到以下输出:

When I call this function from the end of my didMoveToView in my practice Swift project, I get the following output:

Optional("shape_blueSquare") 与 Optional("Category2147483648") 可选("shape_blueSquare") 与Optional("shape_redCircle") Optional("shape_blueSquare") 与可选(shape_purpleSquare")可选(shape_blueSquare")碰撞与可选(shape_yellowTriangle")可选(shape_redCircle")与可选碰撞(类别 2147483648")Optional("shape_redCircle") 与 Optional("shape_blueSquare") 碰撞Optional("shape_redCircle") 联系时通知可选(shape_purpleSquare")可选(shape_redCircle")碰撞与可选(shape_yellowTriangle")可选(shape_redCircle")联系 Optional("shape_yellowTriangle") 时通知Optional("shape_purpleSquare") 与 Optional("Category2147483648") 可选(shape_purpleSquare")与可选的(shape_yellowTriangle") 可选的(shape_yellowTriangle")与 didBeginContact 输入的所有内容发生冲突可选(shape_purpleSquare")和可选(shape_redCircle")为 Optional("shape_purpleSquare") 输入了 didBeginContact 和Optional("shape_redCircle") didBeginContact 输入可选(shape_yellowTriangle")和可选(shape_redCircle")

Optional("shape_blueSquare") collides with Optional("Category 2147483648") Optional("shape_blueSquare") collides with Optional("shape_redCircle") Optional("shape_blueSquare") collides with Optional("shape_purpleSquare") Optional("shape_blueSquare") collides with Optional("shape_yellowTriangle") Optional("shape_redCircle") collides with Optional("Category 2147483648") Optional("shape_redCircle") collides with Optional("shape_blueSquare") Optional("shape_redCircle") notifies when contacting Optional("shape_purpleSquare") Optional("shape_redCircle") collides with Optional("shape_yellowTriangle") Optional("shape_redCircle") notifies when contacting Optional("shape_yellowTriangle") Optional("shape_purpleSquare") collides with Optional("Category 2147483648") Optional("shape_purpleSquare") collides with Optional("shape_yellowTriangle") Optional("shape_yellowTriangle") collides with everything didBeginContact entered for Optional("shape_purpleSquare") and Optional("shape_redCircle") didBeginContact entered for Optional("shape_purpleSquare") and Optional("shape_redCircle") didBeginContact entered for Optional("shape_yellowTriangle") and Optional("shape_redCircle")

类别 2147483648 是我的边缘边界,它没有名称.我给它这个类别以匹配它的碰撞位掩码

Category 2147483648 is my edge boundary and it does not have a name. I gave it this category to match its collisionBitMask

请随时尝试此功能,如果它有用或有任何无法处理的情况,请告诉我.

Please feel free to try this function and let me know if it's useful or if there are any situations it does not handle.