【问题标题】:Swift GameplayKit pause GKAgent without pausing sceneSwift GameplayKit 暂停 GKAgent 而不暂停场景
【发布时间】:2016-02-23 14:26:02
【问题描述】:

暂停 GKAgent 的最佳方式是什么?

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

我不会在我的游戏中暂停整个 SKScene,而是暂停一个 worldNode,因为它让我可以更灵活地显示 spriteKit 内容,即使在游戏暂停时也是如此。

我正在使用

 updateWithDeltaTime...

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

我考虑过停止更新方法,但代理仍会移动到他们最后一个已知的 GKGoal。

到目前为止,我发现的最佳解决方案是在游戏暂停时将代理速度/maxSpeed 设置为 0。我在这里遇到的问题是,在恢复时将速度重置为代理以前的速度有点痛苦,尤其是在使用具有自己行为的多个代理时。它们似乎也消失了,然后在恢复时重新出现。

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

在不暂停 SKScene 本身的情况下暂停代理的好方法是什么?

感谢您的任何帮助和建议。

【问题讨论】:

  • 您是否尝试在 agentDidUpdate 中设置某些内容?类似于如果 gameIsPaused 跳转并且不更新节点位置?
  • 我会试一试。我查看了苹果演示机器人示例,它们停止了代理的所有 updateWithDelta 方法。实际上我现在也设法做到了,但是在恢复时它们会发生巨大的跳跃,因此代理仍然没有正确暂停。再次感谢
  • 我在我的游戏中添加了一个 DeadState,我也遇到了同样的问题,我尝试设置 agent.delegate = nil 和 self.removeComponentForClass 但 agentWillUpdate 和 updateWithDeltaTime(在我的类 MoveWanderAgent 中:GKAgent2D ) 仍然打电话。我发现的唯一方法是检查 updateWithDeltaTime 中的状态:如果 stateMachine.currentState 是 DeadState { behavior = StopBehavoir() return }。我增加了你的问题
  • 是的,正是我的问题。我仍在尝试对 DemoBots 进行逆向工程,以了解 Apple 是如何做到的。应该有一个 agent.paused 方法。
  • 肯定有比将行为设置为不移动更好的方法

标签: swift agents


【解决方案1】:

我想我现在找到了一个似乎可行的解决方案。

首先我会在游戏暂停时停止 udapteDeltaMethods。

我会查看我所有的实体并将代理委托设置为 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 之前进行了几秒钟的大规模跳跃/消失。

【讨论】:

    【解决方案2】:

    您是否在 GameScene 的 update 中添加了 if worldNode.paused { return } 行?

    这对我有用

    游戏场景:

    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 可能会起作用。我会告诉你。谢谢
    • 这实际上是苹果在DemoBots中的更新方法中所做的。令我困惑的是,即使您停止更新,代理仍然会完成他们的最后一个 GKGoal。所以我不确定苹果会做什么来暂停这一切
    • 如果你把你想要暂停的所有代理放在一个像 AgentNode:SKNode 这样的 SKNode 中,并将它添加到你的 worldNode 中,你可以只暂停 AgentNode.paused。你怎么看?
    • 老实说我不知道​​,我试一试。我的实体已经被添加到添加到世界节点的角色节点中,这就是为什么我认为代理也应该暂停,但阅读文档代理只是做他们自己的事情。我会检查一下,然后报告,谢谢
    • 我刚刚找到了一种似乎可行的方法,我刚刚发布了一个答案。希望这对你也有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多