Search code examples
swiftsprite-kitskaction

Stop SKAction after a certain amount of time


I have a number of enemies that spawn at separate times in my game, and move using SKAction but at the end of each level I have a boss that spawns in. When the boss spawns I want the other enemies to stop spawning. I have a function for each enemy. I'm using the withKey: in my SKAction.sequence for each enemy and then use the removeAction(forKey: ) in the boss function to stop it but it doesn't work. Am I using this in a wrong way.

example of my code (only left in the SKAction code, removed all other code)

override func didMove(to view: SKView) {
       //Spawn Enemy1
        run(SKAction.repeatForever(
          SKAction.sequence([SKAction.run() { [weak self] in
                              self?.addEnemy1()
                            },
                            SKAction.wait(forDuration: 5.0)])))

}

func addEnemy1() {
        
        let delay = SKAction.wait(forDuration: 10)
        let actionMove = SKAction.moveTo(y: -600, duration: 5.0)
        let actionRemove = SKAction.removeFromParent()
        enemy1.run(SKAction.sequence([delay, actionMove, actionRemove]), withKey:"enemy1")
        
    }

func addBoss() {
        
        let move1 = SKAction.moveTo(y: size.height / 3.5, duration: 3)
        let move2 = SKAction.moveTo(x: size.width / 3, duration: 3)
        let move3 = SKAction.moveTo(x: 0 - boss.size.width, duration: 3)
        let move4 = SKAction.moveTo(x: 0, duration: 1.5)
        let move5 = SKAction.fadeOut(withDuration: 0.2)
        let move6 = SKAction.fadeIn(withDuration: 0.2)
        let move7 = SKAction.moveTo(y: 0 - boss.size.height * 3, duration: 3)
        let move8 = SKAction.moveTo(y: size.height / 3.5, duration: 3)

        let action = SKAction.repeat(SKAction.sequence([move5, move6]), count: 6)
        let repeatForever = SKAction.repeatForever(SKAction.sequence([move2, move3, move4, action, move7, move8]))
        let sequence = SKAction.sequence([move1, repeatForever])

        boss.run(sequence)
        
        enemy1.removeAction(forKey: "enemy1")
    }

Solution

  • You are removing the wrong action. The action with key "enemy1" is:

    SKAction.sequence([delay, actionMove, actionRemove])
    

    which simply animates the enemy. Removing this only stops this sequence of actions temporarily. When addEnemy1 is called again, the sequence of action is added again.

    The action that spawns the enemy is the action that you run on self here:

        run(SKAction.repeatForever(
          SKAction.sequence([SKAction.run() { [weak self] in
                              self?.addEnemy1()
                            },
                            SKAction.wait(forDuration: 5.0)])))
    

    Yo should give a key to that action instead:

    ...
    },
    SKAction.wait(forDuration: 5.0)])), withKey: "spawnEnemy")
    

    and then remove that from self:

    removeAction(forKey: "spawnEnemy")