sachalondon
sachalondon

Reputation: 165

FPS drops and game slows down - Sprite-Kit and Swift

I have a game using Sprite-Kit and Swift where I generate random circles falling from the top of the screen to the bottom of the screen.

When launching the game, it runs perfectly fine at the beginning (at around 60 FPS or less) but then the FPS drops gradually and the game becomes extremely slow... I don't understand why the FPS drops with time (the number of nodes stays good at around 8-10, so they get removed when they go off the screen) - I tested it on both the iOS Simulator and an actual device, any ideas?

I have checked, the problem isn't coming from a memory leak. Also, I am using only one view controller.

The only function that I think could cause this issue is this one, but I don't know why:

/* Function to generate single random circle */
func generateCircle() -> Void {
    let circleSize:CGFloat = CGFloat(arc4random_uniform(40) + 3)
    let xPosition:CGFloat = CGFloat(arc4random_uniform(UInt32(size.width)))

    var randomCircle = SKShapeNode(circleOfRadius: circleSize)
    randomCircle.strokeColor = SKColor.redColor()
    randomCircle.fillColor = SKColor.redColor()
    randomCircle.physicsBody = SKPhysicsBody(circleOfRadius: circleSize)
    randomCircle.physicsBody?.dynamic = false
    randomCircle.position = CGPoint(x: xPosition, y: size.height + circleSize*2)
    randomCircle.physicsBody?.dynamic = true
    randomCircle.physicsBody?.categoryBitMask = randomCirclesGroup
    addChild(randomCircle)
}

Upvotes: 4

Views: 2992

Answers (3)

Wolfgang Schreurs
Wolfgang Schreurs

Reputation: 11834

SKShapeNode has worse performance compared to SKSpriteNode and one should try to avoid using SKShapeNode if at all possible.

From Apple's documentation:

Shape nodes are useful for content that cannot be easily decomposed into simple textured sprites. Shape nodes are also very useful for building and displaying debugging information on top of your game content. However, the SKSpriteNode class offers higher performance than this class, so use shape nodes sparingly.

If you really want to use SKShapeNodes (perhaps because it's easy for prototyping) I would advise you to do the following:

  • Create textures for your shapes a single time, perhaps when the scene gets loaded.
  • Cache the rendered textures. In your situation a dictionary with size and texture seems appropriate, e.g. [CGSize: SKTexture].
  • From then on, whenever you need a shape, retrieve the texture from the cache and display them using an SKSpriteNode.

To render an SKShapeNode into a texture you can use SKView's textureFromNode function:

Renders the contents of a node tree and returns the rendered image as a SpriteKit texture.

Upvotes: 0

Arkidillo
Arkidillo

Reputation: 91

I've had this before, the node count makes it look they are gone, but they really aren't.

You need to remove the circles from the view to really get rid of them.

First you would define a set (inside your class, but not inside any function)

 let circles = Set<SKShapeNode>()

then in the generateCircle() function you would say:

 circles.insert(randomCircle)

Then in the update() function:

 override func update(currentTime: CFTimeInterval){
      for index in circles {
           if index.position.y <= 0 {
                index.removeFromParent()
                circles.remove(index)
           }
      }
 }

Basically what this does is, at every frame, check if any of the circles are lower than the bottom of the screen, and deletes them if they are.

Upvotes: 1

Luca Angeletti
Luca Angeletti

Reputation: 59536

Maybe there is a memory leak.

  1. Launch your game with Xcode.
  2. Open the Xcode Debug Navigator panel with CMD + 6.
  3. Select Memory and wait to see if the allocated memory grows up.

If this happen, I mean if the allocated memory continue to grow even when you know it should not, then you are leaking memory.

And the best tool to find where exactly is the problem in your code is Instruments.

Upvotes: 3

Related Questions