Unity旋转(四元数)
- 格式:doc
- 大小:1.78 MB
- 文档页数:5
旋转方式:矩阵旋转、欧拉旋转、quateration(四元数)∙矩阵旋转o优点:▪旋转轴可以是任意向量;o缺点:▪旋转其实只需要知道一个向量+一个角度,一共4个值的信息,但矩阵法却使用了16个元素;▪而且在做乘法操作时也会增加计算量,造成了空间和时间上的一些浪费;∙欧拉旋转o优点:▪很容易理解,形象直观;▪表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;o缺点:▪之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;▪会造成万向节锁(Gimbal Lock)的现象。
这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。
理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。
这里有个视频可以直观的理解下;▪由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;∙四元数旋转o优点:▪可以避免万向节锁现象;▪只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;▪可以提供平滑插值;o缺点:▪比欧拉旋转稍微复杂了一点点,因为多了一个维度;▪理解更困难,不直观;Quaternion.eulerAngles 欧拉角表示旋转的角度,绕z轴旋转euler.z度,绕x轴旋转euler.x度,绕y轴旋转euler.y度(这样的顺序)。
Quaternion.AngleAxis 角轴static function AngleAxis (angle : float, axis : Vector3) : QuaternionDescription描述Creates a rotation which rotates angle degrees around axis.绕axis轴旋转angle,创建一个旋转。
unity 旋转原理Unity是一款流行的游戏引擎,它可以用来创建各种类型的游戏。
其中一个重要的功能是对象的旋转。
在 Unity 中,对象可以绕着不同的轴进行旋转,比如绕着 x、y、z 轴等。
那么这些旋转是如何实现的呢?Unity 中的旋转是通过四元数(Quaternion)来控制的。
四元数是一种数学概念,用于描述三维空间中的旋转。
它可以看作是一个复数,由实部和虚部组成。
在 Unity 中,四元数可以使用 Quaternion 类型来表示。
Quaternion 类型有四个成员变量:x、y、z 和 w,分别表示虚部的三个分量和实部。
在 Unity 中,Quaternion 类型的值通常是由Euler 角度(即绕 x、y、z 轴的旋转角度)转换而来的。
在 Unity 中,对象的旋转可以通过修改 Transform 组件的rotation 属性来实现。
rotation 属性的类型是 Quaternion,可以直接赋值一个 Quaternion 类型的值。
比如,要让一个对象绕着 y 轴旋转 90 度,可以这样做:```csharptransform.rotation = Quaternion.Euler(0, 90, 0);```其中 Quaternion.Euler(x, y, z) 表示绕 x、y、z 轴旋转对应的 Euler 角度所构成的 Quaternion 类型的值。
除了直接设置 rotation 属性外,Unity 还提供了一些方便的接口来控制对象的旋转,比如 Rotate、RotateAround 等。
这些接口使用起来比较简单,可以根据具体需求进行选择。
总的来说,Unity 中的旋转是由四元数来控制的,而四元数的值通常是由 Euler 角度转换而来的。
掌握了这些原理之后,就可以在Unity 中灵活地控制对象的旋转了。
Unity面试题(含答案)史上最全的Unity面试题(持续更新总结。
)包含答案的Unity面试题这个是我刚刚整理出的Unity面试题,为了帮助大家面试,同时帮助大家更好地复习Unity知识点,如果大家发现有什么错误,(包括错别字和知识点),或者发现哪里描述的不清晰,请在下面留言,我会重新更新,希望大家共同来帮助开发者一:什么是协同程序?在主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行,协程很像多线程,但是不是多线程,Unity的协程实在每帧结束之后去检测yield的条件是否满足。
二:Unity3d中的碰撞器和触发器的区别?碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。
当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器三:物体发生碰撞的必要条件?两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体,而且必须是运动的物体带有Rigidbody脚本才能检测到碰撞。
四:请简述ArrayList和List的主要区别?####ArrayList存在不安全类型(ArrayList会把所有插入其中的数据都当做Object来处理)?装箱拆箱的操作(费时)?List是接口,ArrayList是一个实现了该接口的类,可以被实例化五:如何安全的在不同工程间安全地迁移asset数据?三种方法1.将Assets目录和Library目录一起迁移2.导出包,export Package3.用unity自带的assets Server功能六:OnEnable、Awake、Start运行时的发生顺序?哪些可能在同一个对象周期中反复的发生Awake –>OnEnable->Start,OnEnable在同一周期中可以反复地发生。
unity物体缓慢旋转到一定角度的方法【实用版4篇】篇1 目录1.旋转速度控制2.旋转角度控制3.使用 Unity 内置函数旋转4.使用C#脚本控制旋转篇1正文在Unity中,让物体缓慢旋转到一定角度有多种方法。
首先,我们可以通过控制旋转速度和旋转角度来实现这一目标。
其次,可以使用Unity 内置函数进行旋转,最后还可以通过编写C#脚本来实现对物体旋转的精确控制。
首先,旋转速度的控制可以通过更改物体的旋转速度矢量来实现。
在Unity 编辑器中,选择物体,然后在 Inspector 面板中找到“Rotation Speed”属性并进行修改。
你也可以在脚本中通过更改该属性的值来实现速度的控制。
其次,旋转角度的控制可以通过设置旋转的目标角度来实现。
在Unity 编辑器中,选择物体,然后在 Inspector 面板中找到“Rotation”属性并输入目标角度。
同样,你也可以在脚本中通过设置该属性的值来实现角度的控制。
Unity 提供了内置函数来实现物体的旋转。
例如,可以使用Quaternion 类的 Slerp 方法来实现物体的缓慢旋转。
Slerp 方法接收三个参数:当前物体的旋转四元数、目标物体的旋转四元数和时间。
通过计算三个参数之间的插值,可以实现物体在指定时间内从当前角度旋转到目标角度。
如果你希望在C#脚本中实现对物体旋转的精确控制,可以编写如下代码:```csharpvoid FixedUpdate(){float rotationSpeed = 1f; // 设置旋转速度float rotationAngle = 10f; // 设置旋转角度float currentTime = Time.fixedDeltaTime; // 获取当前时间// 计算旋转四元数Quaternion currentRotation = Quaternion.Euler(0f, rotationAngle * rotationSpeed * currentTime, 0f);Quaternion targetRotation = Quaternion.Euler(0f, rotationAngle, 0f);// 使用 Slerp 方法实现旋转Quaternion newRotation =Quaternion.Slerp(currentRotation, targetRotation, currentTime);// 应用旋转到物体上transform.rotation = newRotation;}```将这段代码添加到一个 Monobehaviour 类中,并在 Unity 场景中挂载该脚本,即可实现物体的缓慢旋转。
UnityTransform常识(转)Variablesposition: Vector3 物体在世界坐标中的位置。
transform.position=Vector3(10,10,10)//把物体放到(x=10,y=10,z=10)的位置localPosition: Vector3 相对位置,或⾃⾝位置,物体相对于⽗物体的位置。
eulerAngles: Vector3 轴向旋转⾓度,相对于世界坐标。
单位为度(°)localPosition: Vector3 相对轴向旋转⾓度,或⾃⾝的旋转⾓度,物体相对于⽗物体的旋转。
⼀般使⽤和处理物体的旋转⾓度时都会使⽤到这个数值。
right: Vector3 物体⾃⾝的红⾊轴向(X轴)在世界坐标中所指向的位置。
注意在maya中x轴指向物体的左边,⽽unity中的x轴则指向物体的右边。
rigidbody.velotity=transform.right*moveSpeed;//向物体的右侧以moveSpeed的速度移动up: Vector3 物体⾃⾝的绿⾊轴向(Y轴)在世界坐标中所指向的位置。
forward: Vector3 物体⾃⾝的蓝⾊轴向(Z轴)在世界坐标中所指向的位置。
rotation: Quaternion 以四元数来表达的物体⾃⾝的旋转。
四元数可以快速的处理物体的旋转⽅向的计算,搭配Quaternion可以⽤来计算各种需要的旋转⽅案。
具体应⽤⽅法参见Quaternion篇localRotation: Quaternion 相对于⽗物体的⽤四元数来表达的旋转。
localScale: Vector3 物体相对于⽗物体的缩放parent: Transform 物体的⽗物体。
如果没有则返回null。
如果改变⽗物体的位置,旋转和缩放,会同时影响并改变⼦物体的位置,旋转和缩放,但是保持相对位置,相对旋转和相对缩放。
worldToLocalMatrix: Matrix4x4 ⼀个表达从世界坐标到相对坐标位置的四维矩阵,Read Only。
1. 概述在计算机图形学和游戏开发中,经常会遇到向量绕向量旋转的问题。
这个问题涉及到线性代数和三维空间的数学知识,需要用到旋转矩阵和四元数等概念。
本文将以Unity引擎为例,介绍向量绕向量旋转的公式和实现方法。
2. 理论基础在三维空间中,向量可以用坐标表示。
假设有一个向量v,以及一个轴向量axis,我们希望将向量v绕轴axis旋转角度theta。
根据数学知识,我们可以通过旋转矩阵或者四元数来表示这个旋转操作。
2.1 旋转矩阵旋转矩阵是一个3x3的矩阵,可以表示三维空间中的旋转操作。
对于一个单位向量axis,我们可以构造一个旋转矩阵R,使得向量v经过R变换后得到旋转后的向量v'。
具体公式如下:v' = R * vR = cos(theta) * I + (1 - cos(theta)) * axis * axis^T + sin(theta) * [axis]其中,^T表示转置,cos表示余弦函数,sin表示正弦函数,I表示单位矩阵。
这个公式可以将向量v绕轴axis旋转角度theta。
2.2 四元数四元数是一种数学工具,用来表示三维空间中的旋转。
在Unity引擎中,旋转操作一般都是通过四元数来表示。
对于一个单位向量axis,我们可以构造一个四元数q,使得向量v经过q变换后得到旋转后的向量v'。
具体公式如下:v' = q * v * q^(-1)这里的^(-1)表示四元数的逆。
通过构造合适的四元数来实现向量绕轴的旋转。
3. Unity中的实现在Unity中,我们可以通过代码来实现向量绕向量的旋转操作。
以旋转矩阵为例,可以按照以下步骤进行实现:3.1 创建轴向量我们需要创建表示旋转轴的向量。
在Unity中,可以使用Vector3来表示三维向量。
假设我们要绕y轴旋转,可以创建一个向量axis,其x、y、z分量分别为0、1、0。
3.2 计算旋转矩阵根据上述的旋转矩阵公式,我们可以计算出表示旋转操作的矩阵R。
Unity中物体的旋转⽅法代码第⼀种:transform.Rotate(new Vector3(90, 0, 0));//重载⽅式重载⽅式⼀第⼀个参数是 x轴旋转度数,第⼆个参数是 Y 轴旋转度数,第三个参数是Z轴旋转度数,//第四个参数是⾃⾝还是世界坐标public void Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo = Space.Self);//重载⽅式⼆第⼀个参数沿着谁旋转第⼆个参数是旋转的⾓度第三个参数是⾃⾝还是世界坐标public void Rotate(Vector3 axis, float angle, Space relativeTo = Space.Self);// 重载⽅式三第⼀个参数沿着谁旋转第⼆个参数是沿着⾃⾝还是世界坐标⼀般的默认世界旋转public void Rotate(Vector3 eulers, Space relativeTo = Space.Self);using UnityEngine;public class ExampleClass : MonoBehaviour{public float speed; // 速度void Update(){//以每秒1度的速度围绕其局部X轴旋转对象transform.Rotate(Vector3.right * Time.deltaTime*speed);// 以世界坐标的Y 轴进⾏旋转transform.Rotate(Vector3.up * Time.deltaTime, Space.World*speed);}}第⼆种:四元数旋转transform.rotation = Quaternion.Euler(45, 45, 45);// 重载⽅式是⼀个参数是vector3 类型的数据以下那两个只是形式不⼀样public static Quaternion Euler(float x, float y, float z);public static Quaternion Euler(Vector3 euler);using UnityEngine;public class Example : MonoBehaviour{void Start(){// 绕着Y 轴旋转30 度Vector3 rotationVector = new Vector3(0, 30, 0);Quaternion rotation = Quaternion.Euler(rotationVector);}}第三种种:通过四元数⼀个物体以⼀定的速度转向⽬标物体//通过t在a和b之间进⾏球⾯插值,将参数t夹在[0,1]范围内。
unity 万向锁数学原理Unity中的万向锁(Gimbal Lock)是指在旋转物体时,由于旋转轴的限制而导致物体的旋转出现异常的现象。
万向锁的数学原理可以通过四元数来解释。
在Unity中,物体的旋转是通过四元数(Quaternion)来表示的。
四元数是一种复数,可以用来表示三维空间中的旋转。
它由一个实部和三个虚部组成,分别表示旋转轴和旋转角度。
当物体进行旋转时,四元数会不断更新,从而实现物体的平滑旋转。
然而,当旋转轴的角度接近90度时,万向锁现象就会出现。
这是因为在这种情况下,旋转轴的自由度被限制,导致物体的旋转出现异常。
具体来说,当旋转轴的角度接近90度时,旋转轴的两个分量会趋向于重合,使得物体在这两个方向上的旋转无法区分。
这就导致了物体旋转时的不连续性和不可预测性,即万向锁现象。
为了解决万向锁问题,Unity使用了四元数的球面插值(Slerp)来平滑地进行旋转。
球面插值是一种通过沿着球面进行插值来计算旋转的方法。
它可以确保旋转的连续性和平滑性,从而避免了万向锁现象。
具体来说,球面插值通过计算两个四元数之间的插值来实现旋转。
它首先将两个四元数表示的旋转转化为两个四元数表示的球面坐标,然后在球面上进行插值计算,最后再将插值结果转化为四元数表示的旋转。
这样就可以保证旋转的连续性和平滑性,避免了万向锁现象的发生。
除了球面插值,Unity还提供了其他一些方法来解决万向锁问题。
例如,使用欧拉角(Euler Angle)来表示旋转可以避免万向锁现象,但是欧拉角的使用会带来其他问题,如万向锁的倒置问题。
另外,使用四元数的矩阵插值(Matrix Lerp)也可以解决万向锁问题,但是计算复杂度较高。
Unity中的万向锁是由于旋转轴的限制而导致物体的旋转出现异常的现象。
通过使用四元数的球面插值等方法,可以解决万向锁问题,确保旋转的连续性和平滑性。
这些方法在游戏开发中起到了重要的作用,使得物体的旋转效果更加真实和流畅。
unity rotatearound实现原理
Unity中的RotateAround函数是用来围绕一个指定的点旋转物体的。
其实现原理主要基于向量运算和四元数。
首先,你需要指定一个中心点,这个点可以是世界坐标中的一个点,也可以是物体自身的一个局部坐标点。
然后,你需要指定旋转轴,这可以是X轴、Y轴或Z轴,或者是一个自定义的向量。
接下来,你需要指定旋转的角度和旋转的方向。
旋转的方向可以是正向或反向,这取决于你选择的旋转轴和旋转方向。
在实现RotateAround函数时,首先需要计算物体相对于中心点的偏移量,这可以通过取物体的位置向量减去中心点的位置向量得到。
然后,根据旋转轴和旋转方向,对这个偏移量进行相应的旋转操作。
具体来说,如果旋转轴是X轴,那么就需要将偏移量绕X轴进行旋转。
如果旋转方向是正向,那么就需要将偏移量绕X轴逆时针旋转指定的角度;如果旋转方向是反向,那么就需要将偏移量绕X轴顺时针旋转指定的角度。
如果旋转轴是Y轴或Z轴,或者是一个自定义的向量,那么就需要将偏移量绕这个轴或向量进行旋转。
旋转的方向和角度的计算方式与X轴相同。
最后,将旋转后的偏移量加回到物体的位置向量上,就得到了旋转后的物体位置。
需要注意的是,在Unity中,物体的旋转是通过四元数来表示的。
四元数是一种复数形式,可以用来表示三维空间中的旋转。
在RotateAround函数中,需要对偏移量进行四元数旋转操作,然后再将结果转换回普通的向量形式。
unity中quaternion.rotatetowards的用法-回复Unity 是一款非常流行的游戏引擎,其中的Quaternion 类提供了一系列方法来进行旋转操作。
其中就包括了Quaternion.RotateTowards 方法,它允许我们在两个旋转之间插值。
本文将一步一步回答关于Unity 中Quaternion.RotateTowards 方法的用法和功能。
一、Quaternion 类简介在介绍Quaternion.RotateTowards 之前,我们先来了解一下Quaternion 类。
Quaternion 类是Unity 中用于表示旋转的一种数据类型。
与Euler 角度不同,它使用四元数来表示旋转,具有很多优点,例如避免万向节锁等问题。
Quaternion 类中包含了一系列常用的方法,例如旋转插值、从旋转矩阵创建Quaternion 对象等。
其中就包括了我们要介绍的Quaternion.RotateTowards 方法,它可以用来在两个旋转之间进行插值。
二、Quaternion.RotateTowards 方法的定义Quaternion.RotateTowards 是Quaternion 类中的一个静态方法,它的定义如下:public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);该方法接受三个参数:from 表示当前的旋转,to 表示目标旋转,maxDegreesDelta 表示最大旋转角度差。
该方法的返回值是一个新的旋转Quaternion 对象,表示从当前旋转到目标旋转的插值结果。
三、Quaternion.RotateTowards 方法的用途Quaternion.RotateTowards 方法的主要用途是将当前的旋转逐渐插值到目标旋转,使得旋转过程更加平滑。
unity中quaternion.rotatetowards的用法Unity中的Quaternion.RotateTowards用法Quaternion.RotateTowards是Unity引擎中的一个函数,用于旋转一个Quaternion类型的变量,使其逐渐朝着目标角度旋转。
在本文中,我们将详细介绍Quaternion.RotateTowards的用法,并提供一些示例来帮助读者更好地理解这个函数。
首先,让我们来了解Quaternion类型。
Quaternion是表示旋转的一个四元数,它可以用来表示旋转的方向和角度。
Quaternion.RotateTowards 函数就是通过改变Quaternion的角度,来实现旋转的效果。
Quaternion.RotateTowards的函数定义如下:public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);其中from表示当前的角度,to表示目标角度,maxDegreesDelta表示最大旋转角度。
接下来,我们将分为以下几个步骤来逐步回答题目中的问题。
步骤1:创建一个旋转效果的示例场景首先,我们需要在Unity中创建一个示例场景,来演示Quaternion.RotateTowards函数的用法。
我们可以创建一个简单的3D 场景,添加一个旋转的物体或者角色模型,并为其添加一个脚本来实现旋转效果。
步骤2:在脚本中使用Quaternion.RotateTowards函数在脚本中,我们可以使用Quaternion.RotateTowards函数在Update函数中实现旋转效果。
下面是一个示例代码:using UnityEngine;public class RotateObject : MonoBehaviour{public Transform target;public float rotationSpeed = 10f;Update is called once per framevoid Update(){计算当前角度和目标角度之间的差距Quaternion targetRotation =Quaternion.LookRotation(target.position - transform.position);float angleDifference =Quaternion.Angle(transform.rotation, targetRotation);if (angleDifference > 0.1f){使用Quaternion.RotateTowards函数逐渐旋转到目标角度Quaternion newRotation =Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);transform.rotation = newRotation;}}}在上面的示例代码中,游戏对象将逐渐旋转到目标角度。
Unity3D中的Quaternion(四元数)今天,我来总结一下Unity中的四元数得使用。
我也是初学,就写的比较飘逸,难免有错误!四元数的概念四元数,这是一个图形学的概念,一般没怎么见过,图形学中比较常见的角位移的表示方法有“矩阵”、“欧拉角”、“四元数”这三种。
可以说各有各的优点和不足,不同的场合用不同的方法。
其中四元数的优点有:平滑插值、快速连接、角位移求逆、可以与矩阵形式快速转换、仅用四个数表示。
不过,它也有一些缺点:比欧拉角多一个数表示、可能不合法(如:坏的输入数据或者浮点数累计都可能使四元数不合法,不过可以通过四元数标准化来解决这个问题)、晦涩难懂。
那为啥四元数是四个数呢?其实还是有个小故事的。
话说当时十九世纪的时候,爱尔兰的数学家Hamilton一直在研究如何将复数从2D扩展至3D,他一直以为扩展至3D应该有两个虚部(可是他错了,哈哈)。
有一天他在路上突发奇想,我们搞搞三个虚部的试试!结果他就成功了,于是乎他就把答案刻在了Broome桥上。
说到这里,也就明白了,四元数其实就是定义了一个有三个虚部的复数w+xi+yj+zk。
记法[w,(x,y,z)]。
好了,上面我们就基本清楚四元数的作用以及好处与坑了,下面开始正式讲讲Unity中我们如何使用一些常见的四元数操作。
Unity中的四元数基本的旋转,我们可以通过Transform.Rotate来实现,但是当我们希望对旋转角度进行一些计算的时候,就要用到四元数Quaternion 了。
Quaternion的变量比较少也没什么可说的,大家一看都明白。
唯一要说的就是xyzw的取值范围是[-1,1],物体并不是旋转一周就所有数值回归初始值,而是两周。
初始值: (0,0,0,1)沿着y轴旋转:180°(0,1,0,0) 360°(0,0,0,-1)540°(0,-1,0,0)720°(0,0,0,1)沿着x轴旋转:180°(-1,0,0,0) 360°(0,0,0,-1)540°(1,0,0,0) 720°(0,0,0,1)无旋转的写法是Quaternion.identify。
Unity3D一行代码实现一个物体保持面向另一个物体(旋转)今天准备学习和研究下unity3d的四元数 Quaternion四元数在电脑图形学中用于表示物体的旋转,在unity中由x,y,z,w 表示四个值。
四元数是最简单的超复数。
复数是由实数加上元素i 组成,其中i^2 = -1 \,。
相似地,四元数都是由实数加上三个元素 i、j、k 组成,而且它们有如下的关系: i^2 = j^2 = k^2 = ijk = -1 \, 每个四元数都是 1、i、j 和 k 的线性组合,即是四元数一般可表示为a + bi + cj + dk \,。
具体的四元数知识可从百度、维基等网站了解。
/view/319754.htm现在只说说在unity3D中如何使用Quaternion来表达物体的旋转。
基本的旋转我们可以用脚本内置旋转函数transform.Rotate()来实现。
function Rotate (eulerAngles : Vector3, relativeTo : Space = Space.Self) : void但是当我们希望对旋转角度进行一些计算的时候,就要用到四元数Quaternion了。
我对高等数学来说就菜鸟一个,只能用最朴素的方法看效果了。
Quaternion的变量比较少也没什么可说的,大家一看都明白。
唯一要说的就是x\y\z\w的取值范围是[-1,1],物体并不是旋转一周就所有数值回归初始值,而是两周。
初始值: (0,0,0,1)沿着y轴旋转:180°(0,1,0,0) 360°(0,0,0,-1)540°(0,-1,0,0) 720°(0,0,0,1)沿着x轴旋转:180°(-1,0,0,0) 360°(0,0,0,-1)540°(1,0,0,0)720°(0,0,0,1)无旋转的写法是Quaternion.identify现在开始研究Quaternion的函数都有什么用。
Unity 3D中欧拉角与四元数关系在Unity 3D游戏引擎中,物体的方位是用四元数的形式来存储的,但界面上给用户呈现的却是欧拉角。
用户设置的欧拉角会先转化为四元数,最终转化为新的欧拉角,而每一个欧拉角都可以用两个四元数来表示,这样就会使问题变得非常复杂。
这里给出了欧拉角的两种约定和欧拉角与四元数的数学表达式,通过对欧拉角和四元数在Unity3D游戏引擎中的实例应用的分析研究,将两者之间的转换关系做出了详细的说明。
在Unity3D 游戏引擎中,用方位来表征物体的旋转姿态,这是一个状态变量,方位可以采用旋转矩阵、欧拉角和四元数三种方法来描述。
在引擎中采用四元数来定义方位,但四元数不直观,设置困难,因此一般给用户呈现的是欧拉角。
由于欧拉角可以任意设置,理论上同一个方位可以用无数个欧拉角来表示,也可以用两个四元数来表示。
但Unity 3D 引擎只用一个四元数来定义方位,这就造成了四元数与欧拉角一对多(1:n)的问题。
采用四元数定义物体方位又带来另外一个问题,就是同一个方位可以用两个四元数来表示,这又形成了1:2 的问题。
因此同一个方位对应两个四元数和无数个欧拉角。
用户为物体设置好的欧拉角会转化为系统内部的四元数,由系统内部的四元数又可以转化成一个新的欧拉角。
因此转换过程是:用户设置欧拉角→系统内部四元数→新欧拉角。
虽然是同一个方位,但用户设置的欧拉角和系统生成的欧拉角在数据表现上并不相同,这会给学习Unity 3D 游戏引擎带来巨大障碍,这里从欧拉角和四元数的数学定义和转换公式入手,详细阐明其在Unity 3D 中的基本原理,并通过具体实例讲解了两者的应用过程。
欧拉角的概念欧拉角是用来定义方位的一种表示,它有两种约定分别是“heading-pitch-bank”约定和“roll -pitch-yaw”约定。
“heading-pitch-bank”约定是首先把物体坐标系和惯性坐标系对齐,物体旋转顺序为:y → x →z。
Unity复杂的旋转-欧拉⾓和四元数⼀.欧拉⾓欧拉⾓最容易表⽰,⽤三个变量X,Y,Z可以直观的表⽰绕着某个轴的旋转⾓度。
在Unity⾥就是Transform组件的Rotation⾥的X Y Z三个变量代表了欧拉⾓⼆.四元数四元数相⽐于欧拉⾓就⽐较复杂了,由四个变量组成(在Unity中称为X,Y,Z,W),但是这些变量的值不代表旋转⾓度,所以可能给你⼀个向量(0。
7,0,0,0.7)你并不知道实际旋转的⾓度,当然四元数的详细解释需要数学⽅⾯的深⼊研究,有兴趣的可以⾃⾏查找有关资料因为在Unity没有可视化界⾯可以调整四元数(因为真的调了也不直观看到旋转的⾓度),所以我们只能⽤脚本来访问三.脚本中内容欧拉⾓如果在脚本中表⽰呢?是不是想到之前图中的那个Rotation,那你是不是⾃然⽽然的想到了通过transform.rotation访问呢?如果你是这样想的,那就错了!在Unity中transform.rotation代表的是四元数!附上官⽹证明!那到底如何表⽰欧拉⾓呢?其实表⽰很简单,并附上官⽹解释transform.eulerAngles =new Vector3(20,300,40);1当我们以上述代码运⾏后会发现Rotation中的Y值是-60,那是因为⾯板上的Rotation中的X Y Z值范围是在(-180,180),对于代码中超出的部分会⾃动进⾏计算映射到范围内四元数的代码表⽰就是之前的transform.rotation,那你肯定会想欧拉⾓和四元数之前能否转换呢,知道其中⼀个的值,如果改变成对⽅呢?代码如下//欧拉⾓->四元数//通过Quaternion.Euler() 传递⼀个Vector3向量的欧拉⾓transform.rotation = Quaternion.Euler(new Vector3(20, 300, 40));//四元数->欧拉⾓transform.rotation.eulerAngles;//对你没看错直接可以转换获取123456三.区别欧拉⾓:优点:三个⾓度组成,直观,容易理解优点:可以进⾏从⼀个⽅向到另⼀个⽅向旋转⼤于180度的⾓度缺点:死锁问题——万向节死锁万向节死锁介绍四元数优点:不存在万向节死锁问题优点:存储空间⼩,计算效率⾼缺点:单个四元数不能表⽰在任何⽅向上超过180度的旋转。
【转】Unity四元数和向量相乘作⽤及其运算规则作⽤:四元数和向量相乘表⽰这个向量按照这个四元数进⾏旋转之后得到的新的向量。
⽐如:向量vector3(0,0,10),绕着Y轴旋转90度,得到新的向量是vector3(10,0,0)。
在unity中表⽰为:运⾏结果为:复合旋转就是四元数依次相乘,最后乘以向量多来⼏例:想了解其中的运算过程的可以往下看。
将四元数的四个值分别计为:(w,x,y,z),unity中的四元数中的四个数字是(x,y,z,w),不影响下⾯的计算过程。
绕任意轴旋转任意⾓度的四元数为:那么绕着Y轴旋转90度的四元数就是q = (√2/2 , 0 , √2/2 , 0);(unity中这个Quaternion.Euler(0,90,0)打debug的话是(0,√2/2 , 0 , √2/2 ),因为排列顺序是(x,y,z,w),不影响下⾯的计算过程)四元数乘以向量的运算规则为:q * v = (q) *( v) *( q−1);其中:q = (√2/2 , 0 , √2/2 , 0);v,将v向量扩充为四元数(0,v),也就是v = (0 , 0,0 , 10);q−1是四元数q的逆,求逆过程如下:共轭四元数:q*=(w,-x,-y,-z),也就是(√2/2 , 0 , -√2/2 , 0)四元数的模:N(q) = √(x^2 + y^2 + z^2 +w^2),即四元数到原点的距离,计算结果为1四元数的逆:q−1=q*/N(q),也就是q−1 = (√2/2 , 0 , -√2/2 , 0)q * v = q * v * q−1 = (√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10)*(√2/2 , 0 , -√2/2 , 0);四元数乘法公式:按照上述计算公式: q * v = q * v * q−1(√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10) = (0,5√2,0,5√2)(0,5√2,0,5√2) * (√2/2 , 0 , -√2/2 , 0)=(0,10,0,0);将最后得到的四元数(0,10,0,0)变为向量(0,newV),就是newV(10,0,0)。
在Unity 3D中,实现物体旋转有多种方式,如旋转矩阵、欧拉角和四元数等[1]。
旋转需要两个基本参量轴和角,物体从一个方位旋转到另一个方位可以采用多次改变轴和角的方式,依次旋转。
其中,有一种旋转方式是只绕一个轴旋转一次就能达到指定方位,且旋转角度在﹣180°~180°之间,称
这样的旋转方式为最短旋转。
任意指定两个方位,要找出其中的最短旋转并不是一件容易的事。
本文将给出最短旋转的数学描述以及在Unity 3D中实现最短旋转的方法。
最短旋转的数学描述
刚体的运动包括平动和转动。
描述刚体的空间位置,用三维空间坐标点(x,y,z)表示,在Unity 3D中有3个基本坐标系,分别是世界坐标系、惯性坐标系与本地坐标系。
相应的,描述刚体的旋转状态,即方位,是本地坐标系与惯性坐标系所形成的角度变化,采用欧拉角来描述。
由于本文不涉及平移,因此为方便讨论,将惯性坐标系和世界坐标系重合。
众所周知,“两点之间线段最短”,同样两个方位之间也存在类似的关系,即最短旋转,两点之间的距离用两点位置之差来描述。
相应的,两个方位之间的最短旋转用两个方位的四元数之比来描述。
如果方位a的四元数为q1,方位b的四元数为q2,刚体从方位a旋转到方位b的最短旋转的四元数为q,则q = q2÷q1。
设四元数q的4个分量分别是(x,y,z,w),该四元数隐含了旋转轴向量n和旋转角d,设轴向量n 的3个分量为(nx,ny,nz)。
一般将轴n和角d写成“轴角对”的形式,即(n,d)=(nx,ny,nz,d )。
四元数q=(x,y,z,w)与轴角对(n,d)=(nx,ny,nz,d )之间的关系为:
q = (x,y,z,w) = (nx*sin(d/2),ny*sin(d/2),nz*sin(d/2),cos(d/2))
在Unity 3D中,改变欧拉角和改变四元数是两种基本的旋转方式,Unity 3D提供了Lerp和Slerp 两种插值函数,在两个方位之间进行采样插值。
对欧拉角的Lerp插值,很难实现最短旋转,而四元数Slerp函数插值则非常容易实现最短旋转,下面通过例子来进行验证。
在Unity3D中改变欧拉角实现旋转
在Unity 3D中,制作一个空物体,命名为a,该物体位于世界坐标系的原点位置,在其下面放置一个立方体Cube和一个小球Sphere,调整立方体和小球的大小和位置,如下图所示,让小球位于立方体的一个角点。
选中物体a,在Inspector面板上修改参数rotation为(-20,-30,9),这是物体a的欧拉角,结果如下图所示。
复制物体a,重新命名为b。
再次复制物体a,并命名为c,修改b欧拉角为(15, 80, 60),结果如下图所示,要实现的操作是物体c开始与a重合,然后旋转到物体b的位置。
为了能够跟踪物体x的旋转,对x上的小球Sphere,添加代码如下:public class MyDrawPointsPath : MonoBehaviour
{
List<Vector3> points = new List<Vector3>();
void Update()
{
points.Add(transform.position);
for (int i = 0; i < points.Count - 1; i++)
{
Debug.DrawLine(points[i], points[i + 1]);
}
}
}
为实现物体x的旋转,创建代码如下:
public class MyRotation : MonoBehaviour
{
public Transform a, b;
float t;
void Update()
{
Vector3 v = Vector3.Lerp(a.eulerAngles,b.eulerAngles, t);
transform.eulerAngles = v;
t += 0.1f * Time.deltaTime; //每秒变化0.1°
}
}
将该段代码拖拽到物体x上,将场景中的物体a和b拖放到代码的公共变量卡槽a和b上,代码中的Vector3.Lerp是系统提供的插值函数,包括3个参数:起始向量a的欧拉角、结束向量b 的欧拉角、插值t在0~1的取值,运行结果如下图所示。
从图中可以看到,物体x上的小球画出了一条奇怪的轨迹,说明用欧拉角插值不能实现最短旋转。
在Unity3D中改变四元数实现最短旋转
将上面代码中的Update()函数进行修改如下:
void Update()
{
Quaternion q1= a.rotation;
Quaternion q2= b.rotation;
Quaternion q= Quaternion.Slerp(q1, q2, t);
transform.rotation = q;
t += 0.1f * Time.deltaTime;
}
代码中q1和q2分别是a,b的四元数,Slerp是在两个四元数之间进行插值,再次运行,结果如下图所示。
通过观察可以看出,物体c绕某一固定轴一次旋转到了指定位置,实现了最短旋转。
这个旋转过程用语言可以描述为:一个刚体从初始方位为a,其欧拉角为(-20,-30,9),旋转到末方位b,欧拉角为(15,80,60),找到轴角对实现最短旋转。
仿照最短距离,本文给出了最短旋转的概念并给出了最短旋转的数学描述,即两个方位的四元数的比值。
在Unity3D中,通过修改四元数很容易实现最短旋转,并能够直观地给出旋转轴和角,对理解四元数在Unity 3D中的应用具有重要作用。