在 Unity3D 中直接设置 GameObject 的四元数,无需每次都构造新的对象

Posted

技术标签:

【中文标题】在 Unity3D 中直接设置 GameObject 的四元数,无需每次都构造新的对象【英文标题】:In Unity3D setting the Quaternion of a GameObject directly, without constructing a new object every time 【发布时间】:2021-02-17 17:49:18 【问题描述】:

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

我目前的工作代码如下:transform.rotation = new Quaternion(x, y, z, w); 这可以正常工作,它会按照它应该旋转的方式修改它所连接的 GameObject 的旋转。

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

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

【问题讨论】:

手动设置四元数充其量是愚蠢的。据我所知,Unity 的四元数是结构,因此没有 clases 的迁移内存开销(结构是一种值类型,意味着当您分配一个“新”时,它只是将值复制过来) 就创建“新”四元数的惩罚而言,您必须做的工作量来重新创建生成四元数的数学,恕我直言,打败了puprose。 感谢您的评论,抱歉回复晚了!我不是在计算四元数,这就是传感器给我的。实际上,我在转换为 Euler 时遇到了问题,这就是我切换到四元数的原因,因为那时我只是传递值,不能搞砸它们。 :) 我接受的答案适用于此目的。 【参考方案1】:

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

这意味着:

transform.rotation 返回对象当前旋转的副本。因此您不能通过调用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;
    

【讨论】:

【参考方案2】:

来自API: Transform.rotation

不要尝试编辑/修改旋转。

我怀疑这是因为rotation 纯粹是为了方便使用,而实际的转换矩阵仅在函数或属性集调用期间更新。直接修改rotation 不会触发矩阵更新。

您可以尝试修改旋转然后调用rotate(0,0,0),但不能保证这会起作用,因为rotation 可能不是“基本事实”,它甚至可能不会被存储。它可以根据矩阵的请求生成。

【讨论】:

以上是关于在 Unity3D 中直接设置 GameObject 的四元数,无需每次都构造新的对象的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D 中 Generic 动画导入设置和 Root Motion 之间的关系

unity3d中如何设置2个摄像机,使游戏画面中同时出现2个场景,一个主场景,一个缩略图??

在unity3d中想要删除脚本应该点击下拉菜单后选择

unity3d 工程中怎样使用手柄操作

unity3d 中如何去除掉一个GameObject的MeshRenderer

为Unity3D创建素材(3):预设物体(Prefab)