我正在旋转相机以使用四元数查看目标对象。我使用 Quaternion.LookRotation 和 Quaternion.Slerp 使相机在协程内平滑旋转。不幸的是,旋转时相机抖动很大。如何使用当前代码使旋转平滑?
Quaternion targetRotation;
public Transform lookAtObject;
IEnumerator RotateTowardsTarget () {
var duration = 2.0f;
for (float t = 0.0f; t < duration; t += Time.deltaTime) {
targetRotation = Quaternion.LookRotation (lookAtObject.position - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, t / duration);
yield return null;
}
}
Slerp 将第三个参数作为进度而不是实际时间,您可以执行此操作
void Update () {
StartCoroutine(RotateOverTime(transform.rotation,
lookAtObject.rotation, 1f / speed));
}
IEnumerator RotateOverTime (Quaternion originalRotation, Quaternion
finalRotation, float duration) {
if (duration > 0f) {
float startTime = Time.time;
float endTime = startTime + duration;
transform.rotation = originalRotation;
yield return null;
while (Time.time < endTime) {
float progress = (Time.time - startTime) / duration;
// progress will equal 0 at startTime, 1 at endTime.
transform.rotation = Quaternion.Slerp (originalRotation,
finalRotation, progress);
yield return null;
}
}
transform.rotation = finalRotation;
}
您现在可以以秒为单位发送持续时间
目前,您始终以当前旋转方向启动 lerp 并朝向目标。
在您的用例中,您更想要做的是存储初始旋转,并且在初始旋转和目标旋转之间进行插值,例如
IEnumerator RotateTowardsTarget ()
{
var duration = 2.0f;
// store the initial and target rotation once
var startRotation = transform.rotation;
var targetRotation = Quaternion.LookRotation (lookAtObject.position - transform.position);
for (var timePassed = 0.0f; timePassed < duration; timePassed += Time.deltaTime)
{
var factor = timePassed / duration;
// optionally add ease-in and -out
//factor = Mathf.SmoothStep(0, 1, factor);
transform.rotation = Quaternion.Slerp (startRotation, targetRotation, factor);
yield return null;
}
// just to be sure to end up with clean values
transform.rotation = targetRotation;
}
这将使相机在 2 秒内从当前的旋转线性到新的旋转线性