Search code examples
swiftskphysicsbodyskshapenodeskphysicscontact

Node on top of another Node, both with Physics Bodies, Only want to detect most top physics body - SpriteKit / Swift


Creating a game in Swift and SprieKit.

I have 2 nodes, a BridgeNode and WaterNode. One on top of the other.

Both have physics bodies to detect when the player is either on the bridge on in the water. Both nodes are added independently as child nodes of the Scene.

When the player node jumps onto the Bridge, DidBegin detects contact with both the Water and Bridge nodes. I only want it to detect the Bridge node as the player is safely on the Bridge OR if the player is in the water.

func didBegin(_ contact: SKPhysicsContact) {
       // Did Begin Contact - Contact Testing and actions
       let player1 = (contact.bodyA.categoryBitMask == player1Mask) ? contact.bodyA : contact.bodyB
       let other = (player1 == contact.bodyA) ? contact.bodyB : contact.bodyA

    if other.categoryBitMask == bridgeMask {
        print("BRIDGE CONTACT")

    }
    else if other.categoryBitMask == waterMask {
        // Contacted Water
        print("WATER CONTACT")

    }
}

The console is printing both print statements always in a random order.

Hope someone can help me to just detect one or the other.


Solution

  • You mentioned that it is a top-down game, so when you have the bridge on top of the water the player will obviously contact both at the same time, there is no "blocking" of the physicsBody underneath the bridge. You need to do something like this in your SKPhysicsContactDelegate:

    var playerIsOnBridge = false
    
    func didBegin(_ contact: SKPhysicsContact) {
        let player1 = (contact.bodyA.categoryBitMask == player1Mask) ? contact.bodyA : contact.bodyB
        let other = (player1 == contact.bodyA) ? contact.bodyB : contact.bodyA
    
        if other.categoryBitMask == bridgeMask || playerIsOnBridge {
            playerIsOnBridge = true
            print("BRIDGE CONTACT")
        } else if other.categoryBitMask == waterMask {
            print("WATER CONTACT")
        }
    }
    
    func didEnd(_ contact: SKPhysicsContact) {
        let bitmaskA = contact.bodyA.categoryBitMask
        let bitmaskB = contact.bodyB.categoryBitMask
    
        if bitmaskA == bridgeMask || bitmaskB == bridgeMask {
            playerIsOnBridge = false
        }
    }