目录
1 三维空间里的旋转与欧拉角,四元数
1.1 欧拉角比较符合直观
1.2 四元数
1.3 下面是欧拉角和四元数的一些参考文章
2 关于旋转的这些知识点
2.1 使用euler欧拉角旋转
2.2 使用quaternion四元数,w,x,y,z
2.3 使用quaternion四元数,类 Vector3.zero 这种固定坐标了,固定的旋转?
unity%E7%BC%96%E8%BE%91%E5%99%A8%EF%BC%8C%E5%9C%A8unity%E9%87%8C%E9%80%9A%E8%BF%87%E7%9C%8B%E5%90%91%E4%B8%80%E4%B8%AA%E7%89%A9%E4%BD%93%E8%80%8C%E5%AE%9E%E7%8E%B0%E6%97%8B%E8%BD%AC-toc" style="margin-left:40px;">2.4 利用unity编辑器,在unity里通过看向一个物体而实现旋转
2.5 互转
2.5.1 使用Euler转化为quaternion四元数
2.5.2 使用quaternion四元数转化为Euler角
3 逐一测试旋转效果
3.1 直接使用Euler角Vector3(0,30,0)来旋转
3.2 直接使用quaternion四元数旋转
3.3 将quaternion四元数转化为Euler角后旋转
3.4 用欧拉角转成四元数后旋转
3.5 直接用Quaternion.AngleAxis *Quaternion.AngleAxis 实现同时绕着多轴旋转
3.6 直接用Quaternion.AngleAxis *Quaternion.AngleAxis 实现同时绕着多轴旋转
3.7 下面是完整的测试草稿代码
4 未解决的问题
4.1 不了解为啥上面有的时候可以持续旋转,有时候只能旋转1次
4.2 关于下面的匀速代码
5 另外一种匀速代码
1 三维空间里的旋转与欧拉角,四元数
- 欧拉角,四元数,都是用来表达三维空间里的旋转的
1.1 欧拉角比较符合直观
欧拉角与四元数-CSDN博客文章浏览阅读1.6w次,点赞29次,收藏127次。一、欧拉角静态的定义对于在三维空间里的一个参考系,任何坐标系的取向,都可以用三个欧拉角来表现。参考系又称为实验室参考系,是静止不动的。而坐标系则固定于刚体,随着刚体的旋转而旋转。如图所示。设定xyz-轴为参考系的参考轴。称xy-平面与XY-平面的相交为交点线,用英文字母(N)代表。zxz顺规的欧拉角可以静态地这样定义:α\alphaα 是 x-轴与交点线的夹角,β\betaβ 是z-..._欧拉角和四元数的区别https://blog.csdn.net/ViatorSun/article/details/102713679
unity里的E,旋转,很明显表示方式就是欧拉角的3种旋转轴
1.2 四元数
- 我们用复数(两个数字)可以表示二维上的旋转,那么是不是用三个数字(三元数)可以表示三维空间中的旋转呢?数学家告诉我们不是的,要表示三维空间中的旋转,我们得用四元数。
- unity 里不只支持欧拉角,也支持用 四元数,表达三维空间里的旋转
-
四元数的基本数学方程为 : q = cos (a/2) + i(x * sin(a/2)) + j(y * sin(a/2)) + k(z * sin(a/2)) 其中a表示旋转角度,(x,y,z)表示旋转轴。
-
四元数的定义:q = [w,x,y,z]其中w是实部,当然也有资料会把四元数写成q = [x,y,z,w]其中w是实部。这都是正确的
-
注意:四元数q,有q^2 = 1.
若想要某个物体(i,j,k)绕着a(x,y,z)轴旋转θ度。
这个旋转用四元数表示就是q = ((x,y,z)sinθ/2, cosθ/2)
该物体用四元数表示为p = ((j,j,k),0)。
那么旋转之后的物体的点为p′,
则:
通过某个公式能算出p′的值。
Quaternion.AngleAxis (30.0f, transform.right) 这个方法的意思是创建一个四元数表示饶transform.right轴旋转30度。
四元数可以用*操作符来进行多个旋转操作比如:
transform.rotation =
Quaternion.AngleAxis (30.0f, transform.right) * Quaternion.AngleAxis (30.0f,transform.up);
也可以用 Quaternion.Euler 欧拉旋转表示四元数旋转比如:
transform.rotation = Quaternion.Euler (new Vector3 (0.0f, 30.0f, 20.0f)) * Quaternion.AngleAxis (30.0f, transform.forward);
如果想对一个向量做旋转做法如下:
Vector3 someVector = new Vector3 (1.0f,1.0f,1.0f);
Vector3 newVector = Quaternion.AngleAxis(90, Vector3.up) * someVector;Quaternion.LookRotation(某个向量v) 使得物体的朝向和v一致
利用四元数做差值(Quaternion.Slerp)旋转:
transform.rotation = Quaternion.Slerp (transform.rotation,Quaternion.Euler (new Vector3 (0.0f, 30.0f, 0.0f)) * Quaternion.AngleAxis (30.0f, transform.forward),Time.deltaTime * 0.33f);
1.3 下面是欧拉角和四元数的一些参考文章
https://zhuanlan.zhihu.com/p/267359507https://zhuanlan.zhihu.com/p/267359507
https://zhuanlan.zhihu.com/p/513687673https://zhuanlan.zhihu.com/p/513687673
https://www.zhihu.com/question/23005815https://www.zhihu.com/question/23005815
https://zhuanlan.zhihu.com/p/27471300https://zhuanlan.zhihu.com/p/27471300
2 关于旋转的这些知识点
2.1 使用euler欧拉角旋转
- Vector3 rotate1 = new Vector3(0,30,0);
- 在unity里表示,绕着Y轴旋转30度
2.2 使用quaternion四元数,w,x,y,z
- 其中W是实数部分
- xyz是虚数部分
- Quaternion quaternion1 = new Quaternion(0,0,0,0);
Quaternion.AngleAxis (30.0f, transform.right)
2.3 使用quaternion四元数,类 Vector3.zero 这种固定坐标了,固定的旋转?
- Quaternion quaternion2 = Quaternion.identity;
unity%E7%BC%96%E8%BE%91%E5%99%A8%EF%BC%8C%E5%9C%A8unity%E9%87%8C%E9%80%9A%E8%BF%87%E7%9C%8B%E5%90%91%E4%B8%80%E4%B8%AA%E7%89%A9%E4%BD%93%E8%80%8C%E5%AE%9E%E7%8E%B0%E6%97%8B%E8%BD%AC">2.4 利用unity编辑器,在unity里通过看向一个物体而实现旋转
- quaternion2 = Quaternion.LookRotation(new Vector3(0,0,0));
2.5 互转
2.5.1 使用Euler转化为quaternion四元数
- quaternion2 = Quaternion.Euler(rotate1);
2.5.2 使用quaternion四元数转化为Euler角
- rotate2 = quaternion2.eulerAngles;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){//使用euler欧拉角旋转Vector3 rotate1 = new Vector3(0,30,0);//使用quaternion四元数,xyzw?Quaternion quaternion1 = new Quaternion(0,0,0,0);//使用quaternion四元数,类 Vector3.zero 这种固定坐标了,固定的旋转?Quaternion quaternion2 = Quaternion.identity;//利用unity编辑器,在unity里通过看向一个物体而实现旋转//重新给quaternion2赋值quaternion2 = Quaternion.LookRotation(new Vector3(0,0,0));///互转//使用Euler转化为quaternion四元数quaternion2 = Quaternion.Euler(rotate1);//使用quaternion四元数转化为Euler角//给rotate2赋值,需要先定义rotate2Vector3 rotate2 = new Vector3(0,0,0);rotate2 = quaternion2.eulerAngles;}// Update is called once per framevoid Update(){}
}
3 逐一测试旋转效果
3.1 直接使用Euler角Vector3(0,30,0)来旋转
Vector3 rotate1 = new Vector3(0,30,0);
this.transform.Rotate(rotate1);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){//使用euler欧拉角旋转Vector3 rotate1 = new Vector3(0,30,0);this.transform.Rotate(rotate1); }
}
3.2 直接使用quaternion四元数旋转
- w,xyz ,其中w是实数部分,xyz都是*i的虚数部分
- 比如
- new Quaternion(0.866f,0,0,0.5f);
- new Quaternion(0,0,0,0);
- Quaternion.identity;
- //quaternion1不能持续旋转这个方法?this.transform.Rotate(quaternion1);
- //只能用this.transform.rotation 旋转到指定位置,而不能持续旋转
- this.transform.rotation = quaternion1;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){//使用euler欧拉角旋转//Vector3 rotate1 = new Vector3(0,30,0);//使用quaternion四元数,w,xyz ,其中w是实数部分,xyz都是*i的虚数部分Quaternion quaternion1 = new Quaternion(0.866f,0,0,0.5f); //quaternion1不能持续旋转这个方法?this.transform.Rotate(quaternion1); //只能用this.transform.rotation 旋转到指定位置,而不能持续旋转this.transform.rotation = quaternion1;}
}
3.3 将quaternion四元数转化为Euler角后旋转
- quaternion1.eulerAngles 可以将quaternion四元数转化为Euler角
- rotate2 = quaternion1.eulerAngles;
Quaternion quaternion1 = new Quaternion(0.866f,0,0,0.5f);
Vector3 rotate2 = new Vector3(0,0,0);
rotate2 = quaternion1.eulerAngles;
this.transform.Rotate(rotate2);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){Quaternion quaternion1 = new Quaternion(0.866f,0,0,0.5f); Vector3 rotate2 = new Vector3(0,0,0);rotate2 = quaternion1.eulerAngles;this.transform.Rotate(rotate2); }
}
3.4 用欧拉角转成四元数后旋转
// 创建一个表示xx度旋转欧拉角,然后转换为的四元数,表示绕Y轴旋转
Quaternion rotate3 = Quaternion.Euler(0, 45, 0);
// 假设你有一个现有的四元数
Quaternion originalQuaternion = Quaternion.identity;
// 转换为30度旋转
Quaternion newQuaternion = rotate3 * originalQuaternion;
// 应用到游戏对象
this.transform.rotation = newQuaternion;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){// 创建一个表示xx度旋转欧拉角,然后转换为的四元数,表示绕Y轴旋转Quaternion rotate3 = Quaternion.Euler(0, 45, 0);// 假设你有一个现有的四元数Quaternion originalQuaternion = Quaternion.identity;// 转换为30度旋转Quaternion newQuaternion = rotate3 * originalQuaternion;// 应用到游戏对象this.transform.rotation = newQuaternion;}
}
3.5 直接用Quaternion.AngleAxis *Quaternion.AngleAxis 实现同时绕着多轴旋转
- this.transform.rotation = Quaternion.AngleAxis (90.0f, transform.right) * Quaternion.AngleAxis (30.0f, transform.up);
- Quaternion.AngleAxis (90.0f, transform.right) // 绕着right轴X轴旋转90
- Quaternion.AngleAxis (30.0f, transform.up) // 绕着up轴y轴旋转30
- this.transform.rotation 可以实现连续旋转,不知道为啥上面的只能转1次
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){this.transform.rotation = Quaternion.AngleAxis (90.0f, transform.right) * Quaternion.AngleAxis (30.0f, transform.up);}
}
3.6 直接用Quaternion.AngleAxis *Quaternion.AngleAxis 实现同时绕着多轴旋转
- 但是其中一个Quaternion 用欧拉角转化而来
- this.transform.rotation = Quaternion.Euler (new Vector3 (0.0f, 90.0f, 0.0f)) * Quaternion.AngleAxis (30.0f, transform.up);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){this.transform.rotation = Quaternion.Euler (new Vector3 (0.0f, 90.0f, 0.0f)) * Quaternion.AngleAxis (30.0f, transform.up);}
}
3.7 下面是完整的测试草稿代码
如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class rotateTest1 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){//使用euler欧拉角旋转//Vector3 rotate1 = new Vector3(0,30,0);//this.transform.Rotate(rotate1); //使用quaternion四元数,xyzw?//Quaternion quaternion1 = new Quaternion(0,0,0,0);//使用quaternion四元数,类 Vector3.zero 这种固定坐标了,固定的旋转?//Quaternion quaternion2 = Quaternion.identity;//利用unity编辑器,在unity里通过看向一个物体而实现旋转//重新给quaternion2赋值// quaternion2 = Quaternion.LookRotation(new Vector3(0,0,0));///互转//使用Euler转化为quaternion四元数//quaternion2 = Quaternion.Euler(rotate1);//使用quaternion四元数转化为Euler角//给rotate2赋值,需要先定义rotate2//Vector3 rotate2 = new Vector3(0,0,0);//rotate2 = quaternion2.eulerAngles;}// Update is called once per framevoid Update(){//使用euler欧拉角旋转//Vector3 rotate1 = new Vector3(0,30,0);//使用quaternion四元数,w,xyz ,其中w是实数部分,xyz都是*i的虚数部分//Quaternion quaternion1 = new Quaternion(0.866f,0,0,0.5f); //quaternion1不能持续旋转这个方法?this.transform.Rotate(quaternion1); //只能用this.transform.rotation 旋转到指定位置,而不能持续旋转//this.transform.rotation = quaternion1;//Quaternion quaternion1 = new Quaternion(0.866f,0,0,0.5f); //Vector3 rotate2 = new Vector3(0,0,0);//rotate2 = quaternion1.eulerAngles;//this.transform.Rotate(rotate2); // 创建一个表示xx度旋转欧拉角,然后转换为的四元数,表示绕Y轴旋转//Quaternion rotate3 = Quaternion.Euler(0, 45, 0);// 假设你有一个现有的四元数//Quaternion originalQuaternion = Quaternion.identity;// 转换为30度旋转//Quaternion newQuaternion = rotate3 * originalQuaternion;// 应用到游戏对象//this.transform.rotation = newQuaternion;// 多个四元数旋转操作相乘 *,然后转换为的四元数//其中四元数也可以被替换为 欧拉角this.transform.rotation = Quaternion.Euler (new Vector3 (0.0f, 90.0f, 0.0f)) * Quaternion.AngleAxis (30.0f, transform.up);}
}
4 未解决的问题
4.1 不了解为啥上面有的时候可以持续旋转,有时候只能旋转1次
4.2 关于下面的匀速代码
- 不理解下面的匀速代码
- 不理解匀速代码下,为啥改速度没效果?改轴也没效果?
5 另外一种匀速代码
using UnityEngine;public class RotateObject : MonoBehaviour
{// 旋转速度,度/秒public float speed = 30.0f; // 旋转轴public Vector3 axis = Vector3.right; void Update(){// 计算旋转量//Time.deltaTime 是上一帧的时间,可以实现不同机器的匀速播放效果float angle = speed * Time.deltaTime;// 绕axis轴旋转objecttransform.Rotate(axis, angle);}
}