Search code examples
swiftsprite-kitskspritenode

Reduce lagg in Spritekit


I got some lagg in a game I am making in Spritekit. I believe the problem is that I've got to much going on in the "spawn" SKAction.run block. Problem is, I don't know where else to put it. I have tried creating leftcloud and rightcloud outside the createClouds-function, but that causes the app to crash... does anyone know what to do? And will this reduce lagg?

let spawn = SKAction.run ({
                () in
                self.createClouds()
            })

let delay = SKAction.wait(forDuration: 1.2)
let spawnDelay = SKAction.sequence([spawn, delay])
let spawnDelayFE = SKAction.repeatForever(spawnDelay)
let waitSpawnDelayFE = SKAction.sequence([SKAction.wait(forDuration: 2), spawnDelayFE])
self.run(waitSpawnDelayFE)

let distance = CGFloat(self.frame.height)
let moveClouds = SKAction.moveBy(x: 0, y: -distance, duration: TimeInterval(0.0055 * distance))
let removeClouds = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([moveClouds, removeClouds])

func createClouds(){

    cloudpair = SKNode()

    let leftCloud = SKSpriteNode(imageNamed: "cloud2")
    let rightCloud = SKSpriteNode(imageNamed: "cloud2")

    leftCloud.physicsBody = SKPhysicsBody(texture: leftCloud.texture!, size: leftCloud.size)
    leftCloud.physicsBody?.isDynamic = false
    leftCloud.setScale(0.5)
    leftCloud.physicsBody?.affectedByGravity = false

    rightCloud.physicsBody = SKPhysicsBody(texture: rightCloud.texture!, size: rightCloud.size)
    rightCloud.physicsBody?.isDynamic = false
    rightCloud.setScale(0.5)
    rightCloud.physicsBody?.affectedByGravity = false

    leftCloud.position = CGPoint(x: self.frame.width / 2 - 160, y: self.frame.height)
    rightCloud.position = CGPoint(x: self.frame.width / 2 + 160, y: self.frame.height)

    cloudpair.addChild(leftCloud)
    cloudpair.addChild(rightCloud)

    cloudpair.run(moveAndRemove, withKey: "moveclouds")
    cloudpair.name = "cloudpair"
    cloudpair.addChild(scoreNode)
    cloudpair.zPosition = 3
    self.addChild(cloudpair)

    if cloudpair.position.x > 110 {
        rightCloud.removeFromParent()
    } else if cloudpair.position.x < -110 {
        leftCloud.removeFromParent()
    }
}

Solution

  • you are dynamically creating physics bodies on the fly and that is expensive and is probably what is causing your lag.

    what I would do is create an array cloud objects at the load of the scene and then just cycle through them when you need a cloud. This way the objects get created while the scene loads and you get immediate access to the without the lag

    private var leftClouds = [SKSpriteNode]()
    private var rightClouds = [SKSpriteNode]()
    private var currentCloundIndex = 0
    
    func createClouds() {
    
        //assuming your left and right clouds are different
        for x in 0..<10 {
            let leftCloud = SKSpriteNode(imageNamed: "cloud2")
            leftCloud.physicsBody = SKPhysicsBody(texture: leftCloud.texture!, size: leftCloud.size)
            leftCloud.physicsBody?.isDynamic = false
            leftCloud.setScale(0.5)
            leftCloud.physicsBody?.affectedByGravity = false
            leftClouds.append(leftCloud)
        }
    
        for x in 0..<10 {
            let rightCloud = SKSpriteNode(imageNamed: "cloud2")
            rightCloud.physicsBody = SKPhysicsBody(texture: rightCloud.texture!, size: rightCloud.size)
            rightCloud.physicsBody?.isDynamic = false
            rightCloud.setScale(0.5)
            rightCloud.physicsBody?.affectedByGravity = false
            rightClouds.append(rightCloud)
        }
    }
    

    then when you need a cloud just pull it out of the array using currentCloundIndex and then increment currentCloundIndex

    let leftCloud = leftClouds[currentCloundIndex]
    let rightCloud = rightClouds[currentCloundIndex]
    currentCloundIndex += 1
    
    if currentCloundIndex >= 10 {
        currentCloundIndex = 0
    }