Swift GameplayKit如何暂停GKAgent而不暂停场景。

3

如何最好地暂停GKAgent?

我的游戏在某些关卡中使用了一些代理,当我的游戏暂停/游戏结束时,我需要暂停它们。

我不会暂停整个SKScene,而是暂停worldNode,因为这样即使游戏暂停,它也可以给我更多的灵活性来展示SpriteKit内容。

我正在使用

 updateWithDeltaTime...

方法来更新我的代理的行为并相应地移动它们。

我想过停止更新方法,但是代理仍然会移动到它们最后已知的GKGoal。

到目前为止,我找到的最好解决方案是在我游戏暂停时将代理速度/最大速度设置为0。我在这里遇到的问题是,恢复时有点难以将速度重置为代理先前的速度,特别是当使用具有自己行为的多个代理时。它们在恢复时似乎消失了,然后重新出现。

据我所知,没有agent.paused方法或类似的方法.

有没有一种好的方法可以暂停代理而不暂停SKScene本身?

感谢您的帮助和建议。


你尝试过在agentDidUpdate中设置一些东西吗?比如,如果游戏暂停了,就跳过更新节点位置的操作? - Simone Pistecchia
我会尝试一下。我已经查看了苹果的演示机器人示例,并停止了所有代理的updateWithDelta方法。现在我也成功做到了,但是在恢复时它们会产生巨大的跳跃,因此代理仍然没有正确暂停。再次感谢。 - crashoverride777
我在我的游戏中添加了一个DeadState,但仍然遇到同样的问题,我尝试设置agent.delegate = nil和self.removeComponentForClass,但agentWillUpdate和updateWithDeltaTime(在MoveWanderAgent : GKAgent2D类中)仍会被调用。我找到的唯一方法是在updateWithDeltaTime中检查状态:如果stateMachine.currentState是DeadState,则行为为StopBehavoir(),并返回。 - Simone Pistecchia
是的,完全就是我的问题。我仍在尝试反向工程DemoBots以查看Apple是如何做到的。应该有一个agent.paused方法。 - crashoverride777
肯定有比将行为设置为不移动更好的方法。 - crashoverride777
2个回答

1
我觉得我现在找到了一个似乎可行的解决方案。
首先,当游戏暂停时,我会停止更新Delta方法。
然后,我会查看所有实体并将代理委托设置为nil。
  for entity in baseScene.entityManager.entities {
        if let soldier = entity as? BossWorld3Soldiers {
            soldier.agentComponent.delegate = nil
        }
    }

当我恢复游戏时,我调用这个。
  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]))
        }
    }

resetAgentDelegate() 方法只是实体类中的一个便捷方法,用于重置代理。
 func resetAgentDelegate() {
    self.agentComponent.delegate = self
 }

在恢复代理之前,我使用了轻微的延迟来重置代理,因为如果没有延迟,实体/代理似乎会在几秒钟内做出巨大的跳跃/消失,然后才恢复他们的GKGoals。


0
你在GameScene的update方法中是否加入了这行代码:if worldNode.paused { return }
这对我很有效。 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)

    }

是的,如果你愿意的话,你可以这样做,只需要确保在你想暂停游戏时才调用它即可。我认为将委托设置为0可能会起作用。我会让你知道的。谢谢。 - crashoverride777
这实际上是苹果在DemoBots中的update方法所做的。让我困惑的是,即使您停止更新,代理仍将完成其最后一个GKGoal。因此,我不确定苹果公司如何暂停所有操作。 - crashoverride777
如果您将所有要暂停的代理放在一个SKNode(例如AgentNode: SKNode)中,并将其添加到worldNode中,那么您只能暂停AgentNode.paused。您认为呢? - Simone Pistecchia
说实话,我不知道,但我会试一试。我的实体已经被添加到角色节点中,而这些节点又被添加到世界节点中,所以我认为代理也应该暂停,但是根据文档,代理们只会按照自己的方式行动。我会去查看并回报情况,谢谢。 - crashoverride777
我刚找到了一种看起来可以解决问题的方法,我刚刚发布了一个答案。希望这对你也有所帮助。 - crashoverride777

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接