Камера 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 по мере движения камеры.