1

I was quite surprised that the update method in the SKScene class isn't actually inherited from SKNode. To me, it seems logical for all SKNodes to be able to update themselves (for instance to remove itself from the scene when it's no longer on display, among other things). I think this would help in making the instances separate independent entities (no dependencies, no unexpected behavior) If there is other logic behind keeping the updates in the scenes only, please explain.

So I'm wondering if it's worth using a timer (repeating with a 1/60 time interval) to add a custom update to my custom SKNodes (perhaps even an extension that will add this to all SKNodes). However, I imagine this will be quite memory intensive. So I would like to ask if there is some 'best practice' regarding this. Perhaps the timer would work if it fired at each frame rather forcing it to fire 60 times a second.

Youssef Moawad
  • 2,846
  • 5
  • 28
  • 50

1 Answers1

6

Absolutely DO NOT use a timer.

SpriteKit has a well defined update cycle and every kind of update (logic, physics, graphics) should happen into a well defined time frame.

If you really want to write the update logic inside your nodes then the best solution is creating your own update method and then manually invoking it from the GameScene.

Let's see a (possible) structured approach

The protocol

protocol Updatable: class {
    func update(currentTime: NSTimeInterval)
}

Making your sprite/node updatable

class Player: SKSpriteNode, Updatable {

    func update(currentTime: NSTimeInterval) {
        // your logic goes here
    }
}

Forwarding the updates from the scene to the nodes

class GameScene: SKScene {

    private var updatables = [Updatable]()

    override func didMoveToView(view: SKView) {
        let player = Player()
        updatables.append(player)
        self.addChild(player)
    }

    override func update(currentTime: NSTimeInterval) {
        updatables.forEach { $0.update(currentTime) }
    }
}

As you can see I am using an Array of Updatables. You should also take care of adding (or removing) new Updatables to the Array when they are added (or removed) to the scene graph.

While it's definitely possible searching the whole scene graph every frame it would be very bad by a performance point of view.

Is this the right way to go?

Personally I don't like writing this kind of code inside my subclasses of SKNode or SKSpriteNode.

I usually create a Logic class. This class is the ones that receives the update events from GameScene. It also receives other "logic events" like:

  1. gameStarted
  2. touchesBegan
  3. touchesEnded

This class contains the pure game logic of the game.

It is something like the Instruction Manual you can find into a board game and it is totally agnostic about the graphics representation of the game entities.

In an ideal scenario I would be able to extract the Logic class from my SpriteKit game and use it with another framework or even with a (non electronic) board game version of the same game.

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • I actually thought of this almost as soon as I submitted the question. However, my approach to managing updatables was different. Instead of keeping an array, I go through all child nodes and use an if let to check if the node is an updatable. Is this safe? – Youssef Moawad Jul 10 '16 at 20:28
  • 2
    @YoussefSami Searching all the `Updatables` is safe __BUT__ there are 2 huge drawbacks. __1)__ By a performance point of view it's very bad. It means that every frame you are performing a search through your scene graph. It is very expensive and it would be better caching this list like I showed you. __2)__ Keep in mind that some `Updatables` could not be direct children of `GameScene`. They could be children of a child of `GameScene`. So it's not a simple for. It's a full visit of your scene graph. – Luca Angeletti Jul 10 '16 at 20:31
  • @LucaAngeletti caching `updatables` is a great idea. Do you mind expanding on what you mean by the `Logic` class or can you point me to an example project? Is this a better pattern that caching `updatables`? I had some objects that were rarely in the scene but needed to be updated when they were. Instead of searching the scene graph, I the objects use a repeated `update` SKAction with a short `wait` between each call. This feels similar to the Timer approach, which you say isn't good. – muZero Dec 23 '21 at 06:27
  • @muZero Too many questions for a comment. Please create new questions here on StackOverflow and add the links here, I will have a look. – Luca Angeletti Feb 19 '22 at 12:12