1
votes

What is an effective method to perform instantaneous hit detection in SpriteKit? Using SpriteKit's built in physics engine I want to collect affected objects during a single frame for situations such as an explosion's blast radius.

I have considered adding an SKNode with SKPhysicsBody to the explosive object and accessing its allContactedBodies property when it explodes but this would add unnecessary collision detection to other frames.

I have also considered adding an SKNode with SKPhysicsBody to the scene or altering an existing one at the time of explosion and using an action to remove or restore the node after a short duration but this feels unnecessarily complex and may delay the hit detection until the next frame.

I have wondered if there is a means to extend SKPhysicsWorld to allow for enumerating bodies with a circle in addition to a rectangle - or to extend SKPhysicsBody to allow manual collision detection with another test body. However, I do not see how to access an SKPhysicsBody's shape data to do either of these.

1

1 Answers

0
votes

If I were to tackle this problem I would do it by creating a node with a physics body and then messing with its dynamic, categoryBitMask, and collisionBitMask properties. I would set dynamic to false since theoretically the collision/explosion doesn't move because it hits other objects. I would set its categoryBitMask so that every object generated a "didBeginContact" report when colliding with it. And I would set its collisionBitMask so that it never caused impulses because of collision. This way the physicsBody is more of a probe then an actual physics object, just being what is their.

At the end of that the physics body should cause collision reports but not repel any objects. Obviously you can create this body and just not have it added to the scene until it is actually time to detect things. Then after that frame is over and you know all the physics bodies it touched you can remove it again.

Then I would set the scene as a physicsContactDelegate and impliment the did begin contact method.

class GameScene: Scene, SKPhysicsContactDelegate  {
func didBeginContact(contact: SKPhysicsContact)
    {
        var AName:NSString = NSString(string: contact.bodyA.node!.name!)
        var BName:NSString = NSString(string: contact.bodyB.node!.name!)

        }
}

Then I would have if statements checking if either AName or BName were the name of your "probing" node/physicBody. Then after that you can add code to do whatever you want as a result of that collision.

Good luck! If you are having troubles with the bit mask properties I would strongly suggest checking out this.