IOS SpriteKit - Collisions and Contacts not working as expected

Sometimes in my SpriteKit programs my collisions and contacts (using SKPhysicsBody) don't fire or work as expected. I think I have created everything I need, but I still am not getting the correct interactions. How can I easily check what will collide with what and which bodies are set up to create contacts?

+3


source to share


1 answer


To help diagnose these problems, I wrote a function that can be called from anywhere and that will analyze the current scene and make a list of nodes that others are colliding with and which collisions in my scene will be notified.

The function is standalone and does not need to talk about nodes in the scene.

The function is as follows:

            //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 category against every other node 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:

  • the scene should beSKPhysicsContactDelegate

  • You must install physicsWorld.contactDelegate = self

  • You need to implement one of the additional methods SKPhysicsContactDelegate

    :

didBeginContact



didEndcontact

The function should be called after you've set up all your photos - usually it didMoveToView

works at the end :

checkPhysics()

      

When I call this function from the end of mine didMoveToView

in my Swift project in practice, I get the following output:

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 option ("shape_yellowTriangle") Optional ("shape_redCircle") collides with optional ("Category 2147483648") Optional ("shape_redCircle") collides with optional ("shape_blueSquare") Optional ("shape_redCircle") notifies when accessed Optional ("shape_pquare ) Optional ("shape_redCircle") collides with option ("shape_yellowTriangle") Optional ("shape_redCircle") notifies when accessing 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 BeginContact has done, entered for Optional ("shape_purpleSquare") and optional ("shape_redCircle") didBeginContact entered for optional ("shape_purpleSquare") and OptionalCircleCircle ("shape_purpleSquare") and OptionalCircle entered for Optional ("shape_yellowTriangle") and optional ("shape_redCircle")

Category 2147483648 is my edge border and has no name. I gave it this category according to its collisionBitMask

Please feel free to try this feature and let me know if it's helpful or if there are any situations that it doesn't handle.

+4


source







All Articles