SpriteKit 相机动作非常 jerky/laggy

SpriteKit camera actions being very jerky/laggy

我正在使用 Swift 3.0 和 Xcode 8.2.1,在 iPhone 6s 运行 iOS 10.2 上进行测试。

我只是试图以正在减速的速率旋转 SKCameraNode(即它同时具有 angular 速度和加速度)。

这是我目前的解决方案,是的,我知道这很奇怪:

 cam.run(
    SKAction.repeatForever(
        SKAction.sequence([
            SKAction.run
                {
                    self.cam.run(SKAction.rotate(toAngle: 0.0, duration: 0.7, shortestUnitArc: true))
                },
            SKAction.wait(forDuration: 0.1)])))

相机的 zRotation 从某个非零位置开始,然后调用它。然后它每 0.1 秒调用一次 SKAction.rotate 部分。此处未显示,但我让它在 3 秒后终止。

这提供了我想要的确切效果,因为每次调用 SKAction 时,zRotation 更接近其 0.0,但到达那里所需的时间保持在 0.7,因此它的速率接近 0.0 会减速。

然而,以下 3 件事中的 1 件由此发生:

  1. 它按预期完美运行
  2. 感觉每0.1秒就停又续
  3. 一旦调用 SKAction,相机就会立即完全停止作为相机的功能,并且玩家只会一直盯着同一个地方看,直到相机切换。

我尝试将 waitForDuration 从 0.1 减少到 0.01,但它总是执行选项 3。

在使用相机方面,是否有某种 "rules of execution" 是我没有遵循的?

谢谢!

您可以使用单个 rotate(toAngle:) 动作,当相机的 zRotation 接近结束角度时减速,并将 timingMode 属性 设置为 .easeOut.例如,

cam.zRotation = CGFloat.pi
let action = SKAction.rotate(toAngle: 0, duration: duration, shortestUnitArc: true)

// Slows when zRotation is near 0
action.timingMode = .easeOut

cam.run(action)

或者,您可以定义自己的计时函数,通过将 timingMode 语句替换为

来自定义缓出行为
action.timingFunction = {
    time in
    // Custom ease-out, modify this as needed
    return 1-pow(1-time, 5)
 }

此外,您可以使用以下方法计算动作的持续时间,因此 angular 速度和加速度是一致的,无论起始角度如何(即旋转量)

let duration = TimeInterval(normalizedArcFromZero(angle:cam.zRotation)) * 3

func normalizedArcFromZero(angle:CGFloat) -> CGFloat {
    let diff = angle.mod(dividingBy:CGFloat.pi*2)
    let arc = CGFloat.pi - (diff + CGFloat.pi).mod(dividingBy:2 * CGFloat.pi)
    return abs(arc)/CGFloat.pi
}

最后,由于上述需要执行 "floored" 除法的模函数(而不是 Swift 的 truncatingRemainder),您需要将其添加到您的项目中

extension CGFloat {
    func mod(dividingBy x:CGFloat) -> CGFloat {
        return self - floor(self/x) * x
    }
}