と の差はの値に応じてから まで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)
}