Unity--四元数详解

更新时间:2023-06-17 12:07:06 阅读: 评论:0

Unity--四元数详解
Quaternion类
Quaternion(四元数)⽤于计算Unity旋转。它们计算紧凑⾼效,不受万向节锁的困扰,并且可以很⽅便快速地进⾏球⾯插值。 Unity内部使⽤四元数来表⽰所有的旋转。
Quaternion是基于复数,并不容易直观地理解。 不过你⼏乎不需要访问或修改单个四元数参数(x,y,z,w); ⼤多数情况下,你只需要获取和使⽤现有的旋转(例如来⾃“Transform”),或者⽤四元数来构造新的旋转(例如,在两次旋转之间平滑插⼊)。
⼤部分情况下,你可能会使⽤到这些函数:
Quaternion.LookRotation,
Quaternion.Angle
Quaternion.Euler
Quaternion.Slerp
Quaternion.FromToRotation
Quaternion.identity。
Quaternion 是⼀个结构体,本⾝成员变量相对简单,可以作为函数参数⾼效传递。
Unity默认⽅向
在深⼊了解API之前,我们需要先明确⼀些基本的概念,就是⽅向、旋转究竟是如何表⽰的。
Unity中使⽤左⼿坐标系,假如把世界坐标系跟东南西北进⾏结合起来看,⼤致如下图所⽰:
默认的⽅向对应如下表:
坐标轴对应⽅向
+x右(东)
-x左(西)
+y上
-
y下
+Z前(北)
-Z后(南)
假设以你⾃⼰⾝体为例,你站⽴在地⾯上,⾯朝北⽅,此时就是默认⽅向,也就是Unity中的⽅向就是⾯向+Z轴⽅向,那么此时+X轴在东⽅,+Y轴对应正上⽅。此时对应的欧拉⾓是(0,0,0),此时对应的前⽅⽮量是(0,0,1),上⽅⽮量是(0,1,0)。
这⾥我区分了左右上下前后的概念,因为这些概念同时也对应了Vector3类、Transform类中的相应的⽅向函数。
⽅向的表⽰法
①欧拉⾓表⽰法
假如你使⽤⼀组欧拉⾓表⽰旋转,XYZ三个参数代表相应轴向按照顺归YZX的旋转,因此(0、90、90)代表先进⾏+Z轴旋转90度,再沿着+Y轴进⾏90度旋转,更多详细内容可以参考前述⽂章。
②前⽅上⽅⽮量界定法
编程过程中,⼤部分需要明确指定⽅位的时候就需要使⽤这个⽅法。要确定⼀个朝向,我们可以使⽤两个向量来确定:即前⽅⽮量和上⽅⽮量。当⼀个朝向的前⽅和上⽅确定之后,这个朝向也就完全确定了。
举例来说,如果现在只提供⼀个朝向,就是你现在⾯朝北⽅,那么这个⽅向已经完全确定了吗?显然没有。因为你右侧躺在地上,看向北⽅,还是在⾯朝北⽅,这时候就需要另外⼀个⽮量,也就是上⽅。当给出上⽅之后,这个朝向就完全确定了。
上⽅需要严格给出吗?
在Unity中,我们很多时候,不需要给出严格的上⽅朝向。⽐如,仍然是上⾯那个例⼦,如果我⾯朝北⽅,先给出(0,0,1)代表我的前⽅⽮量。那么,如果我给出的⽅向不是严格的上⽅⽮量,⽐如是(0,0.5,0.5),是否可以?答案也是可以的,因为这两个⽮量显然已经确定了⼀个⽅向,前⽅是严格的,⽽实际的上⽅可以通过前⽅朝着你给出的上⽅⽮量旋转90度得出。也就是说,你给(0,1,0)作为上⽅⽮量,和给出在下图中弧度范围内(不包含+Z和-Z)所有⽅向的⽮量都是相同的结果。
③绕轴旋转界定法
考研面试英语自我介绍
第三种定义旋转的⽅法就是围绕某个指定的轴向旋转⼀定的⾓度。这个⽅法也可以确定⼀个相对旋转,它以从默认⽅向(此时前⽅+Z,上⽅+Y)出发,沿着指定的轴向进⾏指定⾓度的旋转,旋转后的前⽅和上⽅是确定的。因此这个⽅法也可以⽤来确定朝向。
④A向到B向相对旋转表⽰法
还有⼀种⽅法就是从A向到B向的相对旋转,这种表⽰了⼀个旋转的相对变化。⽐如A为(0,1,0),B为(0,0,1),也就是相对旋转量代表原来的上⽅被旋转到了前⽅,这样的⼀个四元数也可以⽤欧拉⾓表⽰成(90,0,0),也就是沿着+X轴旋转了90度。
注意上⾯四中表⽰⽅法中,有的明确表明了上⽅⽮量,有的好像只明确了前⽅⽮量,要明确的⼀点就是,它们都是从默认⽮量出发的,如果没有明确指定上⽅朝向,那么就是使⽤默认的上⽅,也就是+Y⽅向。
成员变量
eulerAngles 欧拉⾓,返回当前四元数所对应的欧拉⾓
this[int] 可以使⽤类似数组和下标的形式从四元数中获取四个四元数参数
x、y、z、w 分别代表x、y、z、w 参数,具体代表的内容可以参考前⽂,你最好不要通过修改四个参数来改变四元数,除⾮你真的⾮常了解它们的含义。
静态成员
identity 单位四元数,也就是默认的⽆旋转状态,此时与世界坐标相同,前⽅指向+Z,上⽅指向+Y
成员函数
函数形式解释
void Set(float new_x, float new_y, float new_z, float new_w)设置x、y、z、w 分量,与this[]功能相同
void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection)设置成静态函数FromToRotation的结果
void SetLookRotation(Vector3 view, Vector3 up = Vector3.up)设置成静态函数LookRotation的结果
void ToAngleAxis(out float angle, out Vector3 axis)设置成静态函数AngleAxis的结果
说明:成员函数⼏个t⽅法多⽤于将当前四元数设置成⽬标四元数,⽬标四元数的构建⽅法与对应名
称的静态函数相同。
静态函数
函数形式解释
static float Angle(Quaternion a,
Quaternion b)
计算两个四元数前⽅⽮量之间的夹⾓度数
static Quaternion AngleAxis(float
angle, Vector3 axis)
构建⼀个四元数,它表⽰沿着⼀个轴旋转固定⾓度,即上述表⽰法③
static float Dot(Quaternion a, Quaternion b)计算两个四元数之间的点积,返回⼀个标量,这个函数⼀般⽤不到,它的点积不代表什么具体的物理含义,具体定义⽅法见我的前述⽂章
static Quaternion Euler(float x,
float y, float z)
构建⼀个四元数,它⽤欧拉旋转表⽰,即上述表⽰法①
static Quaternion
FromToRotation(Vector3
fromDirection, Vector3
toDirection)
构建⼀个四元数,它表⽰从指向fromDirection⽅向到指向toDirection⽅向的相对旋转量,见上述表⽰法④
static Quaternion
Inver(Quaternion rotation)构建⼀个四元数,它是指定的四元数的逆,也就是逆向旋转,⽐如原四元数表⽰相对+X轴旋转了90度,那么此函数结果就是相对+X轴旋转了-90度
static Quaternion Lerp(Quaternion a, Quaternion b, float t)构建⼀个四元数,表⽰从四元数a到b的球
⾯插值,所谓的插值也就是中间旋转量,从a作为起点,此时对应t为0,到b为终点,此时对应t为1。当t取0-1之间的⼩数时,就代表了中间的插值结果。这个⽅法与Slerp相同,计算速度快,但是精度低,如果相对旋转变化量很⼩,则效果不理想
static Quaternion
LerpUnclamped(Quaternion a,
Quaternion b, float t)
bec剑桥商务英语与Lerp相同,区别是,Lerp的t值会被钳制在[0,1]之间,⽽此⽅法则不会,t允许超出计算
static Quaternion
LookRotation(Vector3 forward,
Vector3 upwards = Vector3.up)
构建⼀个四元数,使⽤前⽅上⽅⽮量确定朝向,也就是上述表⽰法②
static Quaternion
RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)构建⼀个四元数,表⽰从⼀个四元数from(的前⽅)向着另外⼀个四元数(的前⽅)旋转,但不能超出指定的⾓度,也就是如果两个前⽅⽮量夹⾓超过指定⾓度,则旋转到达指定⾓度时就停⽌,若是夹⾓本⾝不⾜的话,则结果直接为⽬标四元数to,与上述表⽰法④的意思很接近
static Quaternion Slerp(Quaternion
a, Quaternion b, float t)
球⾯插值,与Lerp功能相同,t值也被钳制,计算精度⾼,但是速度相对较慢
static Quaternion
SlerpUnclamped(Quaternion a,
Quaternion b, float t)
与Slerp功能相同,只是t值不被钳制,允许超出计算
static Quaternion operator * (Quaternion lhs, Quaternion rhs)乘法运算符重载,当表⽰两个连续的旋
转时,可以使⽤lhs * rhs的形式得出连续旋转的结果,lhs为左值,rhs为右值。注意左值是先进⾏的旋转,叠加右值旋转。⽤法⽰例:lhs = lhs * rhs;
static Vector3 operator * (Quaternion rotation, Vector3 point)乘法运算符重载,表⽰对⼀个⽮量point施加旋转rotation,得出旋转后的结果⽮量。⽤法⽰例:Vector3 result=rotation * point
验证前⽅上⽅⽮量表⽰法
高一英语必修2为了验证前⽅上⽅⽮量表⽰法的实际上⽅会重新计算,我设计了以下⼩实验。
在场景中设置三个物体,它们的朝向是打乱的,从左到右分别对应1、2、3。可以使⽤以下代码将三个物体朝向调整为⼀致。
//前⽅上⽅⽮量界定法的实际上⽅会重新计算
ation = Quaternion.LookRotation(Vector3.forward, Vector3.up);
eta是什么意思ation = Quaternion.LookRotation(Vector3.forward, new Vector3(0,0.5f,-0.5f));
ation = Quaternion.LookRotation(Vector3.forward, new Vector3(0,0.5f,0.5f));
在start⽅法中执⾏上述代码后,如下:
三个物体朝向是⼀致的,也就说明了上⽅⽮量确实是进⾏了重新计算。
总结⼏种表⽰⽅法
下⾯使⽤代码总结⼏种表⽰法,对应同样的四元数,⼤致有四种表⽰⽅法。
//旋转量的4种表⽰形式
Quaternion q1=Quaternion.Euler(90, 0, 0);
Quaternion q2 = Quaternion.LookRotation(Vector3.down ,Vector3.forward);
Quaternion q3 = Quaternion.AngleAxis(90,Vector3.right);
Quaternion q4 = Quaternion.FromToRotation(Vector3.up, Vector3.forward);
料理鼠王英文版showQ("q1",q1);
showQ("q2",q2);
showQ("q3",q3);
showQ("q4",q4);
它们的输出结果是:开服装店
送东阳马生序翻译也就是说,这⼏种形式表⽰的四元数结果完全相同。ibuki
the lottery将四元数旋转应⽤于⼦弹射击⽰例
当枪管转动起来,⼦弹仍然沿着正确的朝向发射出去,可以使⽤很简单的⼏句话,修改之前的代码后如下:
Bullet_2 bullet = m_compPool.takeUnit<Bullet_2>();
//发射时,将⼦弹的初始位置为枪⼝的当前位置
bullet.m_transform.position = m_transform.position;
//将⼦弹的初始化旋转设置为指向当前枪⼝前⽅
bullet.ation = Quaternion.LookRotation(m_transform.forward);
⼀、简介
闽南话翻译Quaternion⼜称四元数,由x,y,z和w这四个分量组成,是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的数学概念。四元数的乘法不符合交换律。从明确地⾓度⽽⾔,四元数是复数的不可交换延伸。如把四元数的集合考虑成多维实数空间的话,四元数就代表着⼀个四维空间,相对于复数为⼆维空间。
四元数
关于四元数的性质、与旋转的关系、球型线性插值的介绍,请阅读,在此不多做介绍。下⾯主要介绍的是Unity中的四元数-Quaternion。

本文发布于:2023-06-17 12:07:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/975395.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:旋转   函数   指定   朝向   对应   代表
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图