通过检查器窗口设置四元数

Posted

技术标签:

【中文标题】通过检查器窗口设置四元数【英文标题】:Setting Quaternion through inspector window 【发布时间】:2020-07-07 09:42:53 【问题描述】:

我正在寻找一种 (x, y, z, w) 的方法。当我们在 Unity 中单击“调试”模式时,我们会得到所有这些变量。通过 Unity 文档,我了解到这些值介于 0-1 之间。那么我们如何设置角度,例如 90,-90,180,-180,270,.... 这里主要是我想在这个游戏对象的脚本中设置目标旋转,以便游戏对象从初始旋转移动到目标回转。 例如在“正常”窗口中,如果我将 x 的目标旋转设置为 180(在检查器窗口中显示为 -5.008956e-06),则游戏对象从 0 移动到 -180,而不是 +180。这就是我移至“调试”窗口的原因,认为这里设置它有帮助。但是这里的值介于 0-1 之间,那么有人知道如何计算吗?

此外,对于旋转,我正在使用这一行:

transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, Time.deltaTime * RotationSpeed);

【问题讨论】:

你为什么想要直接设置四元数?它不应该是必需的,您可以在您的问题中添加您想要实现的目标吗?四元数适用于非常复杂的数学,除非您完全理解它们(从您不理解的问题来看),否则不应直接设置四元数,正如四元数docs 中所指出的那样。您可以使用函数 Quaternion.Euler(); 输入 eulerangles,Unity 将为您计算四元数,这是任何人在 99.9% 的情况下都应该需要的 感谢您的回复。我想在这里实现的是我希望游戏对象从它的初始旋转旋转到它的最终旋转。 @Saif 使用 public Vector3 targetRotationV3; 并将其应用于 var targetRotation = Quaternion.Euler(targetRotationV3); 有什么问题?无论如何:不要 Slerp 使用 Time.deltaTime .. 在这种情况下没有什么意义......而是使用一个常数因子,例如0.5f ... @derHugo 谢谢你,但我不关注你。常数因子是什么意思,如果我使用欧拉,它告诉我浮点数是不允许的。你能举个例子解释一下吗? 【参考方案1】:

听起来您希望能够通过 Vector3 来调整它,就像 Unity 在 Transform Inspector 中所做的那样。你可以做类似的事情

public Vector3 targetRotationV3;

private Quaternion targetRotation;

private void Start()

    targetRotation = Quaternion.Euler(targetRotationV3);

或者如果您需要更灵活

private void Update()

    targetRotation = Quaternion.Euler(targetRotationV3);

    ...

    

那么对于我的评论,我的意思是Slerp01 之间使用factor 在第一个和第二个参数之间插入一个值。

由于您每一帧都使用一个新值作为起点,即当前旋转,因此到最后会越来越慢,具体取决于您给定的speed 永远不会达到目标旋转。

在这里使用Time.deltaTime 几乎没有意义,它只是将您的速度除以大约60(对于 60 FPS)。通常您更希望在01 之间有一个恒定的插值因子。如果帧速率上升,它甚至可能会旋转回来,因为在这种情况下,Time.deltaTime 会变小!

所以你要么宁愿想要一个恒定的插值因子

[Range(0f,1f)] private float slerpFactor = 0.5f;

private void Update()

    targetRotation = Quaternion.Euler(targetRotationV3);

    transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, slerpFactor);

或者如果您想以恒定速度旋转,请改用Quaternion.RotateTowards

private void Update()

    targetRotation = Quaternion.Euler(targetRotationV3);

    transform.localRotation = Quaternion.RotateTowards(transform.localRotation, targetRotation, Time.deltaTime * RotationSpeed);

您的RotationSpeed 现在在° / second 中的位置

【讨论】:

完美!!所以常见的解决方案是永远不要通过检查器窗口设置四元数,而是使用 Vector3,然后使用 Quaternion.Euler() 函数将其转换为四元数。我现在也理解slerpFactor :)【参考方案2】:

正如我在评论中所说,永远不要直接设置四元数,除非您对自己对它们的理解非常有信心,正如 unity docs 中指出的那样(强调我的)。

它们是基于复数的,不容易直观理解。 您几乎从不访问或修改单个四元数组件 (x,y,z,w);大多数情况下,您只会采用现有的旋转(例如来自变换)并使用它们来构建新的旋转(例如在两个旋转之间平滑插值)。您 99% 的时间使用的四元数函数是:Quaternion.LookRotation、Quaternion.Angle、Quaternion.Euler、Quaternion.Slerp、Quaternion.FromToRotation 和 Quaternion.identity。 (其他功能仅用于异国用途。)

您想要做的是将初始旋转和目标旋转设置为检查器中的Vector3(欧拉角),并使用Quaternion.Euler(); 中的构建方法让Unity 计算出从欧拉角到四元数的转换。

这看起来像这样(请注意,我在示例的更新中执行此操作,并使用我从检查器更新的浮点 time 来更改旋转,这只是为了便于示例和不是实现Quaternion.Slerpt 参数的最佳方法):

public Vector3 initialrotation;
public Vector3 targetRotation;
public float time;

void Update()

    // Let Unity figure out what the appropriate Quaternions are for the given Eulerangles
    // Note that this can better be done in Start if initialRotation and targetRotation never change. Just put it here for simplicity
    var initialQuaternion = Quaternion.Euler(initialrotation); 
    var targetQuaternion = Quaternion.Euler(targetRotation);

    var slerp = Quaternion.Slerp(initialQuaternion, targetQuaternion, time);
    transform.rotation = slerp;

【讨论】:

非常感谢!我永远不会通过检查器窗口设置四元数。最好用作 Vector3。没想到会这么复杂。

以上是关于通过检查器窗口设置四元数的主要内容,如果未能解决你的问题,请参考以下文章

龙格库塔(Runge-Kutta)法求四元数微分方程

Unity复杂的旋转-欧拉角和四元数

结合具有不同枢轴点的四元数

FBXSDK,使用四元数设置旋转键?

在 1 轴上旋转四元数?

OSG 四元数Quat