我认为Unity 3D RotateTowards无法正常工作需要一个阈值

时间:2018-07-06 02:49:41

标签: c# unity3d

我有以下代码,可以使对象以平滑的速度向目标点旋转。

public bool RotatedTowards(Vector3 lookAtPoint, float deltaTime)
{
    flatDirPath = Vector3.Scale((lookAtPoint - transform.position), new Vector3(1, 0, 1));
    targetRotation = Quaternion.LookRotation(flatDirPath, Vector3.up);
    transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, deltaTime * basicProperties.turnRate);
    if (Vector3.Dot(flatDirPath.normalized, transform.forward) >= 0.9f)
    {
        return true;
    }
    else
    {
        return false;
    }        
}

效果很好,问题是如果我在某个点上单击鼠标右键以非常快地移动(告诉该对象以非常高的频率朝向非常相似但不同的lookAtPoint旋转),则该对象会随着其运动而稍微摇动不断进行小的轮换更改(我相信这是发生了什么)。

我认为最好的解决方案可能是仅在目标点距对象前方的阈值超过阈值时才执行transform.rotation,即距对象已经存在的方向的左侧或右侧至少1度面对。我该如何测试?如果低于1度,则不会有任何点朝着它旋转,这应该可以消除因快速单击同一点而产生的抖动。我希望。

感谢您的帮助。谢谢

1 个答案:

答案 0 :(得分:0)

您可以使用以下命令:https://docs.unity3d.com/ScriptReference/Quaternion.Angle.html

在您的代码中:

public bool RotatedTowards(Vector3 lookAtPoint, float deltaTime)
{
    flatDirPath = Vector3.Scale((lookAtPoint - transform.position), new Vector3(1, 0, 1));
    targetRotation = Quaternion.LookRotation(flatDirPath, Vector3.up);

    float angle = Quaternion.Angle(transform.rotation, targetRotation);
    float threshold = 1;

    if(Mathf.Abs(angle) > threshold)
        transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, deltaTime * basicProperties.turnRate);

    return (Vector3.Dot(flatDirPath.normalized, transform.forward) >= 0.9f);       
}

如果您不喜欢此阈值的行为,可以尝试另一种方法:

使用Queue<Vector3>存储最近的flatDirPath个向量(例如,最后10个),然后每次添加一个新向量,并每次删除最旧的向量-然后从所有向量中计算平均向量队列中的向量,并在Quaternion.LookRotation中使用它-您应该获得更平滑的行为。旋转会滞后一点,因为您存储在队列中的向量更多,因此请使用4-6个向量以获得更快的响应,或使用10-20个向量获得更平滑的响应。