ios - 跟随玩家时 SpriteKit 相机卡顿

标签 ios swift sprite-kit skaction skcameranode

我在游戏中遇到这种滞后或卡顿现象,我认为这可能是由于我让摄像机跟随我的玩家的方式所致。

代码如下:

func update(_ hp: CGPoint) {
    let camMove = SKAction.move(to: CGPoint(x: hp.x, y: hp.y), duration: 0.2)
    self.run(camMove)
}

上面的函数是SKCameraNode的扩展,我基本上是从场景更新函数中调用它。

它运行良好,尽管有人提到卡顿可能是由于重叠 Action 造成的,因为它在每一帧都被调用。我使用这种方法是因为持续时间允许相机更自然地跟随,而不是僵硬。

我正在寻找替代方案来消除这种 SKAction 重叠。

我尝试在运行新 Action 之前添加一个 removeallActions() 调用,但它必须发生得很快,因为相机根本没有移动。此外,我尝试在 Action 中添加一个键并在下一个开始之前通过键删除,但与 removeallActions() 相同,相机不会移动。

我也试过以下方法:

func moveCam(_ point: CGPoint) {
    let camMove = SKAction.move(to: CGPoint(x: point.x, y: point.y), duration: 0.2)
    self.run(camMove) {
        self.moveCam(player.position)
    }
}

这会停止重叠,但在一个 Action 结束和另一个 Action 结束之间会有轻微的延迟,这会导致不断出现难看的卡顿。

我有一个想法尝试使用 SKAgents 进行跟随行为,但我不完全确定这将如何完成或是否会很好。任何建议或解决方案将不胜感激。

最佳答案

你想在 sprite 位置发生变化时执行此操作,所以我建议使用 KVO 来监控这一点,并相应地更新你的操作:

override func didMove(to view:SKView) {
  super.didMove(to:view)
  sprite.addObserver(self, forKeyPath: #keyPath(SKNode.position),
              options: [.old, .new, .initial],
              context: nil)
}

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?, change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {

  if keyPath == #keyPath(SKNode.position) {

    guard let camera = self.camera, let sprite = object as? SKNode else { fatalError() }

    let wait = SKAction.wait(forDuration: 0.2)
    let loop = SKAction.customAction(withDuration: TimeInterval(CGFloat.infinity)) {_,_ in
      let move = SKAction.move(to: CGPoint(x: self.sprite.position.x, y: self.sprite.position.y), duration: 0.2)
      camera.run(SKAction.sequence([move,SKAction.run({
        camera.removeAction(forKey:"cameraWaitKey")})]), withKey:"cameraMoveKey")
    }

    if camera.action(forKey:"cameraWaitKey") == nil {
      camera.run(SKAction.sequence([wait,loop]), withKey:"cameraWaitKey")
    }
  }
}


deinit { sprite.removeObserver(self, forKeyPath: #keyPath(SKNode.position)) }

这将做的是应用一个小的等待,然后在每次位置改变时开始移动相机。一旦相机到达播放器,它就会重置,当你再次移动时,就会发生延迟。

您可以将 timingMode 添加到您的操作中,以在相机移动时创建 easeIn 和 easeOut 效果。

关于ios - 跟随玩家时 SpriteKit 相机卡顿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46922478/

相关文章:

sprite-kit - iOS SpriteKit - 碰撞和接触未按预期工作

ios - 在 Swift 应用程序中支付给另一个用户

ios - 使用 Swift 的带有 SpriteKit 的 UISwipeGestureRecognizer

ios - swift : Data passed through unwind segue is erased before being read

ios - iTunesConnect 使用什么图标大小

Swift 和 Firebase 实时数据库 : How do I get the number of objects?

ios - 如何在不删除核心数据中的对象的情况下从干净的托管对象上下文开始

ios - 防止 SKNode 相互施加力

iOS - 使用其他框架依赖项构建静态框架

ios - 当应用程序被终止/强制退出时设置角标(Badge)计数