1

I'm trying to generate new nodes in scene

func generateNewPlatform(inScene: SKScene) {
   for _ in 0...25 {
       let xPosition = randomXPosition()
       let yPosition = randomYPosition()

       let platform = Platform.create(
       platform.position = CGPoint(x: xPosition, y: yPosition)
       inScene.addChild(platform)
   }   
}

I need to generate it every 10 seconds, of course I remove old by

removeFromParent()

But when I do it, it causing frame drop (1-5, depending on the device)

How can I handle this frame drop?

k0le
  • 40
  • 8
  • Try to move all the calculation inside a `DispatchQueue`, only run `addChild` in main queue – Tj3n Jul 25 '18 at 09:26
  • @Tj3n I edit code in question, where I need try to use it? after 'for' before 'addChild'? – k0le Jul 25 '18 at 09:36
  • 1
    It's depends on how you want to write it, if you need update all of them at once, then wrap the loop inside `DispatchQueue` and add `platform` node into an array, then call `removeFromParent ` and `addChild` loop in main queue – Tj3n Jul 25 '18 at 09:46
  • Thank you . I wrap loop in `.global(qos: .userInteractive)` and `addChild` in to main queue and looks like it works. – k0le Jul 25 '18 at 10:12
  • Glads to hear, I have concluded it into the answer – Tj3n Jul 25 '18 at 10:39

2 Answers2

2

You can push the calculation job into background queue to stop them from blocking the UI, maybe the Platform creation is expensive:

func generateNewPlatform(inScene: SKScene) {
    var platforms = [Platform]()
    DispatchQueue.global(qos: .userInitiated).async {
        for _ in 0...25 {
            let xPosition = randomXPosition()
            let yPosition = randomYPosition()

            let platform = Platform.create(..)
            platform.position = CGPoint(x: xPosition, y: yPosition)
            platforms.append(platform)
        }
        DispatchQueue.main.async {
            platforms.forEach {
                inScene.addChild($0)
            }
        }
    }
}
Tj3n
  • 9,837
  • 2
  • 24
  • 35
2

I would not recommend pushing them into the background thread. You are going to run into problems where your game may be at a point where you need a platform but the background thread did not fire in time, thus no platforms are ready for the main thread.

Instead, you should develop a "Loading" phase into your game, and in this phase you load the number of platforms you will need on screen at once and a little bit extra. Then, instead of constantly recreating new platforms, you just recycle the ones that are not on screen, thus no need to waste time and resources on creating new ones.

This is essentially called pooling.

You can then use the background thread method as a backup plan when you find your pool is at a certain % empty. For example, when the pool is down to 10%, fire a background thread to generate more. What this does is still give you the 10% of platforms you need while the background thread generates more nodes.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44