LookRotation用法详解 Unity3d Quaternion.LookRotation实现原理
public static Quaternion LookRotation (Vector3 forward, Vector3 upwards= Vector3.up);
官方解释:
使用指定的 forward 和 upwards 方向创建旋转。
Z 轴将与forward对齐,X 轴与 forward 和 upwards 之间的差积对齐,Y 轴与 Z 和 X 之间的差积对齐。 如果
forward 或 upwards 量值为零,则返回恒等。 如果 forward 和 upwards 共线,则返回恒等。
文档写得很官方,自己研究了一会,总的来说,
LookRotation的作用就是将方向转化为旋转角度:传入一个方向将返回一个旋转角,当某个物体被施加这个旋转角后,这个物体的forward方向将指向传入的方向。
这个方法常常配合transform.rotation = Quaternion.LookRotation()
使用
实验演示:
搭建场景,编写脚本
实验内容:在场景中新建一个正方体和球体,用LookRotation方法将正方体“看向”球体,并绘制输出3条射线。
本文中所有脚本都挂载在正方体上
public class Test: MonoBehaviour{
public Transform sphere;
void Update(){
Vector3 dir = sphere.position - transform.position; //正方体指向球体的向量dir = 球体坐标 - 正方体坐标
Quaternion ang = Quaternion.LookRotation(dir); //创建一个 使正方体朝向球体的旋转角
transform.rotation = ang; //使正方体朝向球体
Debug.DrawRay(transform.position, transform.forward * 100, Color.blue); //绘制正方体forward
Debug.DrawRay(transform.position, dir, Color.green); //绘制向量dir
Debug.DrawRay(transform.position, ang.eulerAngles, Color.red);
}
}
运行场景,单参数解析:
蓝色射线:以正方体的forward为方向,与绿色射线部分重叠。
绿色射线:以欧拉角dir = sphere.position - transform.position
为方向。
红色射线:以四元数LookRotation(dir).eulerAngles
方向,直接绘制很奇怪且无意义。
由上我们可以分析得出:LookRotation()传入一个Vector3方向将返回一个Quaternion旋转角,某个物体被施加这个旋转角后,这个物体的forward方向将对齐传入的Vector3方向。
升级场景,双参数解析
由上我们得知,LookRotation的第一个参数将指定正方体的forward方向,而LookRotation的第二个参数upwards将指定正方体的up和right的方向(即Z轴旋转)。为方便演示,引入圆锥体cone并修改代码如下:
public class Test: MonoBehaviour{
public Transform sphere;
public Transform cone;
void Update(){
Vector3 dir = sphere.position - transform.position;
Quaternion ang = Quaternion.LookRotation(dir, cone.up); //传入第二个参数为cone.up
transform.rotation = ang;
Debug.DrawRay(transform.position, transform.forward * 100, Color.blue);
Debug.DrawRay(transform.position, dir, Color.green);
Debug.DrawRay(transform.position, ang.eulerAngles, Color.red);
Debug.DrawRay(cone.position, cone.up, Color.green); //绘制cone.up方向的绿射线
Debug.DrawRay(cone.position, Vector3.Cross(cone.up, transform.forward), Color.red); //绘制圆锥up方向与正方体forward方向的叉乘方向的红射线
}
}
任意调节圆锥的旋转,效果如下图:
圆锥绿色射线:以cone.up为方向。
圆锥红色射线:以Vector3.Cross(transform.forward, cone.up)
为方向。
由上图可看出,无论怎么旋转圆锥,圆锥红色射线和正方体红色箭头始终方向相同,即圆锥红色射线指定了正方体right的方向。而圆锥绿色射线与正方体绿色箭头并不方向相同,但呈现出了始终共面的特点。
由上我们可以分析得出:若指定第二个参数upwards,则物体的right方向将对齐‘第一个参数’与‘第二个参数’的叉乘方向。
代码手动实现LookRotation()
public Quaternion LookRotation(Vector3 forward)
{
float x = Mathf.Acos(Mathf.Sqrt((forward.x * forward.x + forward.z * forward.z) / (forward.x * forward.x + forward.y * forward.y + forward.z * forward.z))) * Mathf.Rad2Deg;
if (forward.y > 0) x = 360f - x;
float y = Mathf.Atan2(forward.x, forward.z) * Mathf.Rad2Deg;
if (y < 0 || forward.x < 0) y += 180f;
return Quaternion.Euler(x, y, 0f);
}
这样一个简单的单参数LookRotation就实现了,如还需实现双参数的方法,还需求出transform.up与LookRotation()返回值之间的夹角。已知两向量求其夹角的公式:
θ
=
atan
2
(
(
A
⃗
×
B
⃗
)
⋅
norm
(
)
,
A
⃗
∗
B
⃗
)
\begin{matrix} \theta = \operatorname{atan} 2((\vec{A} \times \vec{B}) \cdot \operatorname{norm}(), \vec{A} * \vec{B}) \end{matrix}
θ=atan2((A×B)⋅norm(),A∗B)
但可惜LookRotation()方法内部没法直接拿到transform.up的值,虽然可以通过计算欧拉角的方式间接的求出transform.up,但具体实现过程会变得非常复杂,而且会有万向节死锁问题,暂无法分享示例代码。
LookRotation函数在Unity内部是用C++实现的,然后通过P/Invoke在C#中调用,因此我们无法知晓它的实际源码。而上述代码和码思路仅用于学习和理解LookRotation()的工作原理,实际项目中应该直接使用Unity内置的LookRotation()函数,因为它是经过充分测试和优化的。
更多推荐
所有评论(0)