在 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个场景,一个主场景,一个缩略图??