Is it acceptable to create an SKShapeNode in update delegate?

46 Views Asked by At

I create an SKShapeNode in SpriteKit's update delegate and it works exactly as I want it to. My only concern is that update is called every tenth of a second. Does that mean that my code is also run that often? That doesn't seem very performance friendly. Is there a way around it? Or is it fine having the code on update?

Why is the code in update in the first place you might ask. Well if I put it in didMove or sceneDidLoad then when I rotate the device the node doesn't follow along instantly, it remains in its old place for half a second before relocating to its new position, making it look like it jumps. Bad. Update solves this. Here's the code:

    override func update(_ currentTime: TimeInterval) {
        let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
        mySquare.fillColor = SKColor.blue
        mySquare.lineWidth = 1

        mySquare.position = CGPoint(x: 0, y: 0)
        self.addChild(mySquare)
    }
}
2

There are 2 best solutions below

2
Khalid Afridi On BEST ANSWER

Yes you can create. the only issue you have is it's creating a new node each time update is called. At the moment you can not see multiple nodes because you're positioning them on top of each other if you try to change the position of mySquare on each update call you will see that you have multiple nodes. created which is not effective soon you will run out of frame rates. as you don't have any animations on going you don't see the difference now.

override func update(_ currentTime: TimeInterval) {
    let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
    mySquare.fillColor = SKColor.blue
    mySquare.lineWidth = 1

    mySquare.position = CGPoint(x: randomX, y: randomY)
    self.addChild(mySquare)
}

changing the position of the X and Y will give you the chance to see the nodes being added to different position on the screen.

if for any reason you want to create your mySquare node in the update then you can keep a reference for the node or search the node in the parent node if it's available then don't add any

var mySquare: SKShapeNode

Then in the update check if your Square node is not nil or has the same

override func update(_ currentTime: TimeInterval) {
    if mySquire == nil {
      mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
      mySquire.name = "your square name"
      mySquare.fillColor = SKColor.blue
      mySquare.lineWidth = 1

       mySquare.position = CGPoint(x: randomX, y: randomY)
       self.addChild(mySquare)
   }
}

Note: you can even check for the name like

if mySquare.name == "your square name"

then don't add it any more

4
Maetschl On

Doing anything on the update func is a bad idea

Apple Documentation:

Do not call this method directly; it is called by the system exactly once per frame, so long as the scene is presented in a view and is not paused. This is the first method called when animating the scene, before any actions are evaluated and before any physics are simulated.

If you want to create objects and control them, you should use didMove func for example. And you can create an action like this for example:

self.run(
    SKAction.repeatForever(
        SKAction.customAction(withDuration: 0.0, actionBlock: { (_, _) in
            // Create and add new node...
        })
    )
)

But probably create a several nodes infinitely is a bad idea.