Камера SpriteKit заикается, когда следующий игрок

Я испытываю это отставание или заикание в моей игре, и я думаю, что это может быть связано с тем, как камера следит за моим игроком.

Вот код:

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

Вышеуказанная функция является расширением для SKCameraNode, и я вызываю ее в основном из функции обновления сцен.

Он работает довольно хорошо, хотя кто-то упоминал, что заикание может быть связано с перекрывающимися действиями, поскольку он вызывается каждый кадр. Я использую этот метод, потому что продолжительность позволяет камере следовать более естественно, чем жестко.

Я ищу альтернативы этому, чтобы устранить это перекрытие SKAction.

Я попытался добавить вызов removeallActions() перед запуском нового действия, но это должно произойти быстро, потому что камера вообще не двигается. Кроме того, я попытался добавить ключ к действию и удалить по ключу до следующего запуска, но так же, как и 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)
    }
}

Это останавливает перекрытие, но есть небольшая задержка между одним окончанием действия и другим окончанием, которое постоянно вызывает уродливое заикание.

У меня есть идея попытаться использовать SKAgents с последующим поведением, но я не совсем уверен, как это будет сделано или будет ли это хорошо. Любые предложения или решения будут с благодарностью.

1 ответ

Вы хотите сделать это, когда позиция спрайта изменится, поэтому я бы порекомендовал сделать 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)) }

Для этого нужно немного подождать, а затем начинать перемещать камеру каждый раз, когда положение меняется. Как только камера дойдет до плеера, она будет сброшена, и при повторном движении произойдет задержка.

Вы можете добавить синхронизирующий режим к своим действиям, чтобы создавать эффекты easeIn и easeOut по мере движения камеры.

Другие вопросы по тегам