Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected physicsBody in SpriteKit scene

Tags:

ios

sprite-kit

I'm implementing a mass-spring system (many small physics bodies joined together with SKPhysicsJointSpring instances) with SpriteKit. Some of the particles would get snagged while traversing the center of the scene.

There seems to be a small, static body in the middle of the scene and I don't know why it's there.

Here's an easy way to see what I'm talking about:

  1. In XCode 8, create a brand new project with the "Game" template.
  2. In GameViewController.viewDidLoad(), add view.showsPhysics = true

If you run the project, you should see a little dot in the middle, which is the errant body:

enter image description here

Anyone know how to get rid of it?

Edit: I tried to manually create the scene object:

In GameViewController.viewDidLoad(), I replaced this:

// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
    view.presentScene(scene)
}

with this:

let scene = GameScene(size: view.frame.size)
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
view.presentScene(scene)

but that didn't fix it.

like image 776
scribu Avatar asked Jan 03 '17 14:01

scribu


1 Answers

Anyways, I decided to make an answer because comments are not suitable due to lot of info I want to share. Also my answer, sadly, doesn't answer the question but it gives some useful info about this unidentified, obviously capable of flying (physics body) object :)

So this is the code how to grab it (and modify it???):

 //you can use self.frame here...I just copied Alessandro's code
 self.physicsWorld.enumerateBodies(in:(label?.frame)!) { body, stop in

    if let node = body.node {

        print("Type of this node: \(type(of:node))")    
        print("Frame of this node: \(node.frame))")

    }else{

       print("This body's node property is nil")

        body.affectedByGravity = true
        body.isDynamic = true

        body.applyImpulse(CGVector(dx: 0.003, dy: 0.0003))

    }
     print("Area covered by this node physicsBody: \(body.area)")
}

So if you put a break point inside of that else statement, you can scan this physics body completely and get all the info about it, like that its node property is set to nil or that its isDynamic property is set to false. But you can change that, and like in my code, set for example isDynamics to true. This makes it moveable. So if you apply some forces to it, it will move.

Still, like I said in comments, I don't have an idea why it is there and what it represents or what is its purpose.

Also, for those who are wondering how it is possible that one physics body doesn't have a node associated with it ( body.node equals nil) but is still visible on screen when showsPhysics is set to true, there is a reasonable explanation. Physics world is separated from the node tree. So we can remove a sprite from a node tree, but that doesn't mean that its physics body will be removed instantly. It may happen that physics engine haven't finished simulation... So you probably wonder, how this might happen?

Let say you have three SKSpriteNode objects intersecting at the same time (say A contacts B and A contacts C at the same time). SpriteKit can process only one contact at time. And say that you are removing A from a parent when it is contacting with B. Then, there is a contact between A and C also, so didBegin:(_ contact) will be called twice. And if you remove A from its parent in first didBegin(_ contact) call, in the next didBegin(_ contact) call, bodyA.node will be nil (bodyA is a physics body of sprite A), but its physics body will remain visible until engine finishes what needed. This is because node tree and a physics world are separated.

like image 99
Whirlwind Avatar answered Sep 27 '22 17:09

Whirlwind