旋转
矩阵旋转
求点p(x,y)在围绕原点o(0,0)旋转angle角度后,新的点p1的坐标位置(x1,y1)
使用旋转公式:
//shader中的写法
//新x1坐标 = 原x坐标*cos(角度值) - 原y坐标*sin(角度值),角度值的取值区间是pi = 3.14, 相当于180度。该公式其实就是已知两直角边与夹角求第三遍长
x1 = x * cos(angle) - y * sin(angle);
y1 = x * sin(angle) + y * cos(angle);
欧拉旋转
欧拉旋转的原理是按照顺序旋转坐标轴而实现的,共有12种顺序:X-Y-Z X-Z-Y Y-X-Z Y-Z-X Z-X-Y Z-Y-X X-Y-X X-Z-X Y-X-Y Y-Z-Y Z-X-Z Z-Y-Z 。顺序的不同会导致旋转结果的巨大差异。
unity欧拉旋转使用的是 Y-X-Z的顺序
unity中的旋转
//世界坐标系的欧拉旋转 按照Z-X-Y的顺序依次旋转轴,即先绕z轴旋转90度,再按x轴旋转30度,最后按y轴旋转60度
cube.transform.Rotate(new Vector3(30f, 60f, 90f), Space.World);
//本地坐标系的欧拉旋转 按照Y-X-Z的顺序依次旋转轴,即先绕y轴旋转60度,再按x轴旋转30度,最后按z轴旋转90度
cube.transform.Rotate(new Vector3(30f, 60f, 90f), Space.Self);
四元旋转
用于旋转的四元数,每个分量的范围都在(-1,1);
unity中的四元数
//初始化rotation, 无旋转
myRotation = Quaternion.identity;
//四元数的逆, 返回一个相反的旋转
Debug.Log("相反的旋转为: "+ Quaternion.Inverse(target1.transform.rotation));
//返回欧拉角
Debug.Log("当前rotation的欧拉角为:" + target1.transform.eulerAngles);
//欧拉角转四元数
Debug.Log("欧拉角为0,90,0时,相对应的四元数是:" + Quaternion.Euler(new Vector3(0, 90, 0)));
//欧拉角转四元数并直接做旋转操作
target1.transform.rotation = Quaternion.Euler(new Vector3(0, 90, 0));
//返回两个旋转间的角度
float angle = Quaternion.Angle(target1.transform.rotation, Quaternion.FromToRotation(Vector3.up, transform.forward));
Debug.Log("两个旋转间的角度是: " + angle);
//以指定轴为旋转轴,旋转45度
Quaternion.AngleAxis(45, transform.up);
//在静止状态下,以transform.up为旋转轴顺时针旋转45度
target1.transform.rotation = Quaternion.AngleAxis(45, transform.up);
// *** 不管在静止状态下还是正在旋转中,以transform.up为旋转轴顺时针旋转45度
target1.transform.rotation = Quaternion.AngleAxis(45, transform.up) * target1.transform.rotation;
// 返回一个从Vector3.up到transform.forward方向旋转的四元数
target1.transform.rotation = Quaternion.FromToRotation(Vector3.up, target1.transform.forward);
//获取从target1到target2的方向
Vector3 dirction = target1.position - target2.position;
// 使用四元数,令target1看向target2
target1.transform.rotation = Quaternion.LookRotation(dirction);
void Update()
{
//插值
//已知间隔值为t
float t = Time.deltaTime * 2f;
//旋转四元数
Quaternion q = Quaternion.Euler(new Vector3(0, 90, 0))
//球面插值
target1.transform.rotation = Quaternion.Slerp(target1.transform.rotation, q, t);
//线性插值
target1.transform.rotation = Quaternion.Lerp(target1.transform.rotation, q, t);
}
四元数转换
角转四元数
已知旋转轴向量(x, y, z)与旋转角度θ,求得四元数为q
q = (Xsinθ/2, Ysinθ/2, Zsinθ/2, cosθ/2) = ((X, Y, Z)sinθ/2, cosθ/2)
欧拉角转四元数
已知欧拉旋转度为(Y, X, Z)则旋转顺序为y、x、z(unity中本地坐标的顺序)求四元数
x = sin(X / 2)sin(Z / 2)cos(Y / 2) + cos(X / 2)cos(Z / 2)sin(Y / 2)
y = sin(X / 2)cos(Z / 2)cos(Y / 2) + cos(X / 2)sin(Z / 2)sin(Y / 2)
z = cos(X / 2)sin(Z / 2)cos(Y / 2) - sin(X / 2)cos(Z / 2)sin(Y / 2)
w = cos(X / 2)cos(Z / 2)cos(Y / 2) - sin(X / 2)sin(Z / 2)sin(Y / 2)
q = (x, y, z, w)
物体面向目标
插值面向物体
//目标rotation
Quaternion TargetRotation = Quaternion.LookRotation(player.transform.position - transform.position, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, Time.deltaTime * 1.5f);
实时面向物体
// transform.LookAt(player.transform, Vector3.up);