本帖最后由 da11 于 2021-9-7 12:18 编辑
* 欧拉角
* · 使用三个角度来保存方位。
* · X与Z沿自身坐标系旋转,Y沿世界坐标系旋转。重点 !!
* · API:Vector3 EnulerNum = this.transform.eulerAngles;
*
* 欧拉角的优点:
* · 仅使用三个数字表达方位,占用空间小。
* · 沿坐标轴旋转的单位为角度,复合人的思考方式。
* · 任意三个数字都是合法的,不存在不合法的欧拉角。
* 欧拉角的缺点:(方位的表达方式不唯一)
* · 对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角位移是否相同。
* · 例如:
* --角度0,5,0 与 角度 0,365,0
* --角度0,-5,0 与 角度 0,355,0
* --角度255,0,0 与 角度 290,180,180
* · 为了保证任意方位都只有独一无二的表示,Unity引擎限制了角度范围,既沿X轴旋转限制在-90到90之间,沿Y与Z轴旋转限制在0到360之间。重点!!
* 欧拉角的缺点:(万向节死锁)
* · 物体沿X轴旋转正负90度,自身坐标系Z轴与世界坐标系Y轴将重合,此时再沿Y或Z轴旋转时,将失去一个自由度。
* · 在万向节死锁情况下,规定沿Y轴完成绕竖直轴的全部旋转,既此时Z轴旋转为0。
*
*
*
* 四元数
* · Quaternion 在3D图形学中代表旋转,由一个三维向量(X/Y/Z)和一个标量(W)组成。
* · 旋转轴为V,旋转弧度为θ,如果使用四元数表示,则四个分量为:
* x = sin(θ/2) * V.x y = sin(θ/2) * V.y
* z = sin(θ/2) * V.z w = cos(θ/2)
*
* · X、Y、Z、W的取值范围是-1到1.
* · API:Quaternion qt = this.tranform.rotation;
*
* 四元数与向量相乘
* · 四元数左乘向量,表示将该向量按照四元数表示的角度旋转。
* · 例如:
* Vector3 point = new Vector3(0,0,10);
* Vector3 newPoint = Quaternion.Euler(0,30,0) * point;
*
* 与四元数相乘
* · 两个四元数相乘可以组合旋转效果。
* · 例如:
* Quaternion r1 = Quaternion.Euler(0,30,0) * Quaternion.Euler(0,20,0);
* Quaternion r2 = Quaternion.Euler(0,50,0);
* 结果r1和r2相同。
*
*
* 四元数的优点:
* 避免万向节死锁
* · this.tranform.rotation *= Quaternion.Euler(0,1,0); -- 可使物体沿自身坐标Y轴旋转。 --重点
* · this.tranform.Rotate(Vector3 eulerAngles) -- 内部就是使用四元数相乘实现。--重点
*
* 四元数的缺点:
* · 难于使用,不建议单独修改某个数值。
* · 存在不合法的四元数。
//欧拉角讲解,测试已注释,如需使用请取消注释
/*
private void OnGUI()
{
if (GUILayout.RepeatButton("按x轴旋转"))
{
Vector3 EnuNum = this.transform.eulerAngles;
//注意:欧拉角,没有方向,没有大小概念
//因为三维向量,包含x,y,z,所以在Unity中,欧拉角使用了三维向量的数据类型
//欧拉角的x,y,z,表示各个轴向上的旋转角度。
//Vector3 Pos = this.transform.position;
//位置,有方向(从世界原点指向当前位置),和大小(当前位置到世界原点间距)
//向量的x,y,z,表示各个轴向上的有向位移。
//和欧拉角是不同的
//各分量相加,欧拉角的x轴增加1度
this.transform.eulerAngles += new Vector3(1, 0, 0);
}
if (GUILayout.RepeatButton("按反x轴旋转"))
{
this.transform.eulerAngles += new Vector3(-1, 0, 0);
}
if (GUILayout.RepeatButton("按y轴旋转"))
{
//Vector3.up等于向量的(0,1,0),等同于 EnuNum = EnuNum + new Vector3(0,1,0);
this.transform.eulerAngles = this.transform.eulerAngles + Vector3.up;
}
if (GUILayout.RepeatButton("按z轴旋转"))
{
//Vector3.forward等于向量的(0,0,1),等同于 EnuNum = EnuNum + new Vector3(0,0,1);
this.transform.eulerAngles = this.transform.eulerAngles + Vector3.forward;
}
}
*/
//四元数讲解方法
private void OnGUI()
{
if (GUILayout.Button("设置物体旋转角度"))
{
//使用四元数旋转角度需创建以下代码(需明确旋转轴和旋转弧度)---原理性代码
Quaternion ObjRotation = new Quaternion(); //定义Quaternion类
//旋转轴
Vector3 ZX = Vector3.up; //按y轴旋转
//旋转弧度
float RadNum = 50 * Mathf.Deg2Rad;
/*
ObjRotation.x = Mathf.Sin(RadNum / 2) * ZX.x;
ObjRotation.y = Mathf.Sin(RadNum / 2) * ZX.y;
ObjRotation.z = Mathf.Sin(RadNum / 2) * ZX.z;
ObjRotation.w = Mathf.Cos(RadNum / 2);
this.transform.rotation = ObjRotation;
*/
//使用以下方法可以更快的使用四元数旋转物体,原理和上方的代码一致,为常用方法。
//欧拉角转换为四元数
this.transform.rotation = Quaternion.Euler(0, RadNum * Mathf.Rad2Deg, 0);
}
/*
if (this.transform.gameObject.activeInHierarchy == true)
{
Debug.Log("数学方法宿主方块激活中!!");
}
*/
//以下为没有万向结死锁的通用旋转方法
if (GUILayout.RepeatButton("按反x轴旋转"))
{
this.transform.rotation *= Quaternion.Euler(-1, 0, 0);
//其实this.transform.Rotate(-1, 0, 0); 是和上面的语句一样的,以下同。
}
if (GUILayout.RepeatButton("按x轴旋转"))
{
this.transform.rotation *= Quaternion.Euler(-Vector3.left);
}
if (GUILayout.RepeatButton("按y轴旋转"))
{
//Vector3.up等于欧拉角的(0,1,0);
this.transform.rotation *= Quaternion.Euler(Vector3.up);
}
if (GUILayout.RepeatButton("按z轴旋转"))
{
//Vector3.forward等于欧拉角的(0,0,1);
this.transform.rotation *= Quaternion.Euler(Vector3.forward);
}
if (GUILayout.RepeatButton("设置物体旋转默认值"))
{
this.transform.rotation = Quaternion.Euler(0,0,0);
}
if (GUILayout.RepeatButton("计算右前方10米处坐标位置"))
{
float DistanceLocalPointVarNum = 10; //定义并赋值远端距离变量
Vector3 DistanceLocalPoint = new Vector3(0,0,DistanceLocalPointVarNum); //定义远端的三维向量位置
Vector3 LocalPoint = this.transform.position; //定义本地位置
//计算本地旋转四元数 与 以Y轴为圆心,旋转30度的欧拉度四元数相乘,后乘以 本地坐标加上远端位置坐标,即可达到计算右前方10米处坐标位置的目的,无论物体怎么旋转,对应的都是右前方10米处坐标位置!!
DistanceLocalPoint = (this.transform.rotation * Quaternion.Euler(0, 30, 0)) * (LocalPoint + DistanceLocalPoint);
//将位置使用Debug.DrawLine调试画出来
Debug.DrawLine(LocalPoint, DistanceLocalPoint);
}
}
|