Search code examples
iosswiftswift3game-physicsskphysicsbody

Detect SKPhysicsBody collision after SKPhysicsBody has been applied


I have simple gameplay that functions like this:

enter image description here

My goal is to detect when the ball hits the white part (game over scene would load) or when the ball hits the gray part (game continues)

Because the shapes shrink and have a lot of stuff going on, I figured it would be a lot more efficient to just create the SKPhysicsBody when I need it, and then remove it after the collision checks happen. So when I click the screen this happens: (after 5*0.0325 seconds--how long it takes the circle to shrink--has passed, it will add the physicsbody to both the gray and white part so I can detect which the ball is touching)

DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: {
        let trackPhysics = SKPhysicsBody(texture: track.texture!, size: track.texture!.size())
        trackPhysics.isDynamic = false
        trackPhysics.affectedByGravity = false
        track.physicsBody = trackPhysics

        let goalPhysics = SKPhysicsBody(texture: goal.texture!, size: goal.texture!.size())
        goalPhysics.isDynamic = false
        goalPhysics.affectedByGravity = false
        goal.physicsBody = goalPhysics
    })

Which works. The SKPhysicsBody are applied to both the gray and white part perfectly without any loss in framerate and follow the rotation. The problem is... how do I detect which is the ball touching? Since they did not formally collide, it will not call the collision at all (which makes sense since they did not really collide

This is the basic logic, and it works perfectly until I want to check the results:

  1. someone touches the screen
  2. circles shrink
  3. right after they shrink it will create an SKPhysicsBody for both the gray and white part based on its texture
  4. Problem is here... how do I detect which the ball is touching?

I have tried this:

    func didBegin(_ contact: SKPhysicsContact) {
        print("touching!")
    }

    func didEnd(_ contact: SKPhysicsContact) {
        print("not touching")
    }

which has no messages at all, and have tried using allContactedBodies() 1 second after the SKPhysicsBody were applied, but returns a count with 0 for all of them. I have even tried making this 5 seconds and still not working

DispatchQueue.main.asyncAfter(deadline: .now() + seconds + 1, execute: {
        print(track.physicsBody!.allContactedBodies().count)
        print(goal.physicsBody!.allContactedBodies().count)
    })

This is what it looks like with the SKPhysicsBody applied, you can see the physics is applied perfectly

enter image description here

Am I doing something wrong? Any ideas?


Solution

  • The solution (as discovered in the comments above), was:

    1. Set the isDynamic property of nodes to true for collision detection to work properly.
    2. Ensure that didBegin(contact:) is being called, by double-checking that the scene's physicsWorld.contactDelegate is set.
    3. Ensure the masks and physics bodies are set at the proper times and locations.