targetRadian
和currentRadian
之间0.0
的差异-2π
取决于 的值currentRadian
。该等式将确定转弯的最短方向,.Clockwise
或.CounterClockwise
, 到达targetRadian
:
let turnDirection = (radianDifference + (M_PI * 2)) % (M_PI * 2) < M_PI ? RotationDirection.CounterClockwise : RotationDirection.Clockwise
使用applyTorque
时,可能会过度旋转,targetRadian
从而导致摆动效果,就像指南针向一个点磁化一样,因为旋转来回改变方向以达到targetRadian
。以下虽然不是一个完美的解决方案,但会削弱效果:
let turnDampener = abs(radianDifference) < 1.0 ? abs(radianDifference) : 1.0
因此,完整的解决方案是:
enum RotationDirection: Double {
case Clockwise = -1.0
case CounterClockwise = 1.0
}
func rotateNodeTowardDirectionalVector(node: SCNNode, targetDirectionalVector: (x: Double, y: Double), deltaTime: NSTimeInterval) {
guard abs(targetDirectionalVector.x) > 0.0 || abs(targetDirectionalVector.y) > 0.0 else { return }
let currentRadian = Double(node.presentationNode.rotation.w * node.presentationNode.rotation.y)
let targetRadian = M_PI_2 + atan2(-targetDirectionalVector.y, -targetDirectionalVector.x)
let radianDifference = targetRadian - currentRadian
let π2 = M_PI * 2
let turnDirection = (radianDifference + π2) % π2 < M_PI ? RotationDirection.CounterClockwise : RotationDirection.Clockwise
let absRadianDifference = abs(radianDifference)
let turnDampener = absRadianDifference < 1.0 ? absRadianDifference : 1.0
node.physicsBody?.applyTorque(SCNVector4Make(0, CGFloat(turnDirection.rawValue), 0, CGFloat(deltaTime * turnDampener)), impulse: true)
}