Swift GameplayKit pause GKAgent without pausing scene

418 Views Asked by At

Whats the best way to pause a GKAgent?

My game uses a few agents in some levels and I need to pause them when my game is paused/gameOver.

I dont pause the whole SKScene in my game but rather a worldNode because it gives me more flexibility showing spriteKit stuff even when the game is paused.

I am using the

 updateWithDeltaTime...

methods to update my agents behaviour and move them accordingly.

I thought about stopping the update method but the agents will still move to their last known GKGoal.

The best solution I found so far is setting the agent speed/maxSpeed to 0 when my game is paused. The problem I have here is that upon resume its a bit of a pain to reset the speed to the agents previous speed especially when using multiple agents with their own behaviour. They also seem to disappear and than reappear upon resume.

There is no agent.paused method or something similar as far as I understand.

Whats a good way to pause an agent without pausing the SKScene itself?

Thanks for any help and suggestions.

2

There are 2 best solutions below

0
On BEST ANSWER

I think I found a solution now that seems to work.

Firstly I am stoping the udapteDeltaMethods when the game is paused.

I than look through all my entities and set the agent delegate to nil

  for entity in baseScene.entityManager.entities {
        if let soldier = entity as? BossWorld3Soldiers {
            soldier.agentComponent.delegate = nil
        }
    }

Than when I resume my game I call this

  for entity in baseScene.entityManager.entities {
        if let soldier = entity as? BossWorld3Soldiers {
            let action1 = SKAction.waitForDuration(0.5)
            let action2 = SKAction.runBlock({ soldier.resetAgentDelegate() })
            baseScene.runAction(SKAction.sequence([action1, action2]))
        }
    }

The resetAgentDelegate() method is just a convenience method in my entities classes to reset the agent delegate

 func resetAgentDelegate() {
    self.agentComponent.delegate = self
 }

I am using a slight delay upon resume before resetting the agent delegate because without the delay the enties/agents seem to make a massive jump/dissappear for a few seconds before resuming their GKGoals.

5
On

Do you have put the line if worldNode.paused { return } in update of your GameScene?

This works for me

GameScene:

override func update(currentTime: CFTimeInterval) {

        super.update(currentTime)

        // Don't perform any updates if the scene isn't in a view.
        guard view != nil else { return }

        let deltaTime = currentTime - lastUpdateTimeInterval
        lastUpdateTimeInterval = currentTime

        /*
        Don't evaluate any updates if the `worldNode` is paused.
        Pausing a subsection of the node tree allows the `camera`
        and `overlay` nodes to remain interactive.
        */
        if worldNode.paused { return }

        // Don't perform any updates if the scene isn't in a view.
        guard entityManagerGame != nil else { return }

        entityManagerGame.update(deltaTime)

    }