三个数字来保存方位,共用vector3,但此时它不代表向量。
优点
•仅使用三个数字表达方位,占用空间小。
•沿坐标轴旋转的单位为角度,符合人的思考方式。
•任意三个数字都是合法的,不存在不合法的欧拉角。
//欧拉角,每次叠加(1,0,0)旋转
transform.eulerAngles+=transform.right;
//与前者等效,但实际涵义不同,内部使用的四元数
transform.Rotate(transform.right);
缺点:
对于一个方位,存在多个欧拉角描述,因此无法判断多个欧 拉角代表的角位移是否相同。
例如角度250,0,0与角度290,180,180是同一个欧拉角,难以直观判断。
为了保证任意方位都只有独一无二的表示,Unity引擎限制 了角度范围,即沿X轴旋转限制在-90到90之间,沿Y与Z轴 旋转限制在0到360之间。
欧拉角会造成万向节死锁。
因为欧拉角的缺点,数学家提出了四元数。
缺点:
难于使用,不建议单独修改某个数值。
•存在不合法的四元数。
两个四元数相乘可以组合旋转效果,四元数不能使用+号,表示叠加关系是*号
//物体沿自身y轴旋转1°
transform.rotation *= Quaternion.Euler(0,1,0);
//下面两行等价
//Quaternion.Euler(0, 30, 0) *Quaternion.Euler(0, 20, 0)
//Quaternion.Euler(0, 50, 0);
四元数左乘向量,表示将该向量按照四元数表示的角度旋转:
Vector3 point = new Vector3(0,0,10);
Vector3 newPoint= Quaternion.Euler(0,30,0) * point ;
所以已知一个向量,已知旋转角度,就能求得新向量。
比起三角函数求向量,更为简单!
练习:
//新向量为 当前物体的位置对应的正前方10米,偏转30°
Vector3 newpoint= transform.position+ Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);
练习:求两个物体之间的切线:
脚本绑定在球体上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class aaa : MonoBehaviour
{
public Transform cube;
// Update is called once per frame
void Update ()
{
Vector3 sub = transform.position - cube.position;
float c = sub.magnitude;
//算出夹角,球体半径0.5f
float angle = Mathf.Asin(0.5f / c) * Mathf.Rad2Deg;
//要加上cube.position,因为需要平移
Vector3 leftpoint =cube.position+ Quaternion.Euler(0, angle, 0) * sub;
Vector3 rightpoint = cube.position + Quaternion.Euler(0, -angle, 0) * sub;
Debug.DrawLine(cube.position, leftpoint);
Debug.DrawLine(cube.position, rightpoint);
}
}
正因为四元数和欧拉角各有优缺点,所以unity提供了Rotate函数,它的参数是欧拉角,提供了方便,但内部使用四元数,又避免了欧拉角的缺点。
欧拉角与四元数也广泛使用在unity开发中。
处了前面的那些,Quaternion结构还提供了不少常用的函数:
比如 Quaternion.AngleAxis,作用与 Quaternion.Euler相似;
Quaternion.LookRotation,作用与transform.LookAt相似;
Quaternion.RotateTowards,匀速旋转,类比结构vector3中的vector3.MoveTowards 匀速移动。
Quaternion.Lerp,变速旋转,类比结构vector3中的vector3.Lerp 变速移动。
个人实践经验,可以通过向量来理解四元数的旋转,但必须记住,四元数是一种角度,而不是向量。
Quaternion.LookRotation其含义是把z轴蓝色旋转到某个向量方向需要的角度。
如果unity没有提供LookRotation,完全可以自己实现—需要先算出两个向量的夹角,再根据夹角旋转。
简单用向量理解,把蓝色z轴向量旋转到某个向量方向。
void Update ()
{
if (Input.GetButtonDown("Jump"))
{
transform.rotation = Quaternion.LookRotation(cube.position - transform.position);
}
}
Quaternion.FromToRotation的含义:把某个轴旋转到某个向量方向需要的角度。
transform.rotation= Quaternion.FromToRotation(transform.forward, cube.position-transform.position);
此时的Quaternion.FromToRotation和Quaternion.LookRotation等价。
当我需要把红轴旋转到某个向量方向时:
transform.rotation= Quaternion.FromToRotation(transform.right, cube.position-transform.position);
//需要的角度
Quaternion targ = Quaternion.LookRotation(cube.position - transform.position);
//当前物体角度,需要的角度,每次的增量欧拉角1°
transform.rotation= Quaternion.RotateTowards(transform.rotation, targ, 1);
Quaternion.Angle 也可以算出角度,简易理解为两个物体的蓝色轴或红色轴之间的夹角。
angle = Quaternion.Angle(transform.rotation, cube.rotation);
到目前为止我学了算角度:
① 向量之间的三角函数
②向量的dot 点乘
③vector3.angle, 点乘的简化形式
④Quaternion.Angle,旋转后轴之间的夹角。