在Unity3D中直接设置一个GameObject的Quaternion,不用每次都构造一个新对象

In Unity3D setting the Quaternion of a GameObject directly, without constructing a new object every time

我有一个提供四元数的传感器,我想将其应用于游戏对象。

我目前的工作代码如下:
transform.rotation = new Quaternion(x, y, z, w);
这工作正常,它修改了它附加到的游戏对象的旋转,按照它应该旋转的方式。

但是问题是每一帧都构建一个新对象,看起来很浪费,所以我想修改现有的。我试过以下代码:
transform.rotation.Set(x, y, z, w);
此代码根本不修改游戏对象的旋转。

我可以修改GameObject的四元数而不用每次都构造一个新对象吗?

来自API: Transform.rotation

Do not attempt to edit/modify rotation.

我怀疑这是因为 rotation 纯粹是为了方便起见,实际的变换矩阵仅在函数或 property-set 调用期间更新。因此直接修改 rotation 不会触发矩阵更新。

您可以尝试修改旋转然后调用 rotate(0,0,0),但不能保证这会起作用,因为 rotation 可能不是 'ground-truth',它甚至可能不会被存储。它可以根据矩阵的要求生成。

正如您在 documentation 中看到的那样 Quaternion 是结构,而不是引用类型。

这意味着:

  • transform.rotation returns 对象当前旋转的副本。因此您不能通过调用 transform.rotation.Set(x, y, z, w); 来修改它。您必须使用分配调用。
  • 您不会通过在成员字段中缓存旋转来提高性能,因为赋值无论如何都会复制它,并且您的本地四元数分配在 stack

如果您害怕性能(这不应该只是因为四元数构造),我建议您将 transform 缓存在一个成员中,因为 Unity 的 transform 成员调用 this.gameObject.GetComponent<Transform>() 每次都使用它,这是一个相当昂贵的操作。 尽管为了真正的优化,我们需要知道您的确切代码。

示例:

public class MyClass
{
    // to be used instead of Unity's transform member
    private Transform myTransform;
    
    private void Awake()
    {
        // make expensive call only once during Awake
        myTransform = transform;
    }