CameraWorks 两种旋转模式的实现方法。
模式A
俯仰,偏航,独立于翻滚,平行于世界平面:当前旋转 + delta旋转。
适合类似第一人称射击游戏的操作
模式B
俯仰,偏航,翻滚相互独立:当前旋转四元数 * delta旋转四元数。
可以做到类似 Planetside2 的飞行控制效果
(这里的 Lerp 为了实现非线性插值走了个捷径。正常线性插值请参考这个。)
protected virtual void HandleRotationInput()
{
Vector3 input = CalculateDesiredRotationInput();
smoothedDeltaPitch = Mathf.Lerp(smoothedDeltaPitch, input.x, Time.unscaledDeltaTime * lookSmooth);
smoothedDeltaYaw = Mathf.Lerp(smoothedDeltaYaw, input.y, Time.unscaledDeltaTime * lookSmooth);
smoothedDeltaRoll = Mathf.Lerp(smoothedDeltaRoll, input.z, Time.unscaledDeltaTime * rollSmooth);
if(lookByWorldPlane) {
curEuler += new Vector3(smoothedDeltaPitch, smoothedDeltaYaw, smoothedDeltaRoll);
targetQuaternion = Quaternion.Euler(curAngles);
} else {
deltaQuaternion = Quaternion.Euler(new Vector3(smoothedDeltaPitch, smoothedDeltaYaw, smoothedDeltaRoll));
targetQuaternion *= deltaQuaternion.
}
}
以上是在最终转换成 Quaternion 前,先将输入平滑。如果担心效果不稳定(e.g. 根据帧率,同样大小的输入可能会造成不同程度的旋转)可以先获取目标旋转,再平滑过渡到目标旋转。一般可以直接用 Quaternion.Slerp,但如果仍要独立平滑各轴,还是需要欧拉角。*模式B由于转换原因似乎无法通过这种方法独立平滑各轴。
protected virtual void HandleRotationInput()
{
Vector3 input = CalculateDesiredRotationInput();
if(lookByWorldPlane) {
curEuler += input;
targetEuler = curAngles;
} else {
Quaternion targetQuanternion = Quaternion.Euler(targetEuler) * Quaternion.Euler(input);
targetEuler = targetQuaternion.
}
}
protected virtual void UpdateRotation()
{
if (LookByWorldPlane) {
smoothedEuler.x = Mathf.Lerp(smoothedEuler.x, targetEuler.x, LookSmooth * Time.unscaledDeltaTime);
smoothedEuler.y = Mathf.Lerp(smoothedEuler.y, targetEuler.y, LookSmooth * Time.unscaledDeltaTime);
smoothedEuler.z = Mathf.Lerp(smoothedEuler.z, targetEuler.z, RollSmooth * Time.unscaledDeltaTime);
transform.localEulerAngles = smoothedEuler;
} else {
smoothedQuaternion = Quaternion.Slerp(transform.localRotation, targetRotation, LookSmooth * Time.unscaledDeltaTime);
transform.localRotation = smoothedQuaternion;
}
}