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 件由此发生:
- 它按预期完美运行
- 感觉每0.1秒就停又续
- 一旦调用 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
}
}
我正在使用 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 件由此发生:
- 它按预期完美运行
- 感觉每0.1秒就停又续
- 一旦调用 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
}
}