Unity 点乘和叉乘的原理和使用
点乘
又称点积、数量积、内积定义:a * b =|a||b|cos<a,b>
a、b表示向量,<a ,b>表示向量a,b的夹角,范围[0, 180]
v1和v2向量的点乘运算:相应元素的乘积的和:v1( x1, y1,z1) * v2(x2, y2,z2) = x1x2 + y1y2+z1z2
注意 : 结果不是一个向量,而是一个标量。
Unity应用:
根据点乘计算两个向量的夹角
根据点乘的正负值,判断向量是否同方向
a * b >0 表示夹角少于90度,向量同方向
a * b <0 表示夹角大于90度,向量不同方向
叉乘
又称叉积、向量极、外积定义: c = a * b,其中a b c均为向量
性质: c向量垂直a、b向量,和它们组成的平面
c向量的模长:c=:|a||b|sin<a,b>
叉乘运算:v1( x1, y1,z1) * v2(x2, y2, z2) = (y1z2 - y2z1)+(x2z1 - x1z2)+(x1y2-x2y1)
计算某轴值,则某轴不参与计算,依次顺序相乘
叉乘的右手定则是用来确定叉乘积的方向的。
右手法则:右手的四指方向指向第一个矢量,屈向叉乘矢量的夹角方向(两个矢量夹角方向取小于180°的方向),那么此时大拇指方向就是叉乘所得的叉乘矢量的方向.(大拇指应与食指成九十度)(注意:Unity当中使用左手,因为Unity使用的是左手坐标系)
数学上叉乘的右手法则
Unity当中叉乘的左手法则
Unity应用:
1.根据叉乘得到a,b向量的相对位置,和顺时针或逆时针方位。
简单的说: 点乘判断角度,叉乘判断方向。
形象的说: 当一个敌人在你身后的时候,叉乘可以判断你是往左转还是往右转更好的转向敌人,点乘得到你当前的面朝向的方向和你到敌人的方向的所成的角度大小。
2.得到a,b夹角的正弦值,计算向量的夹角(0,90),可以配合点乘和Angle方法计算出含正负的方向。
3.根据叉乘大小,得到a,b向量所形成的平行四边形的面积大小,根据面积大小得到向量的相对大小。
using UnityEngine;
public class VectorExample : MonoBehaviour {
//点积
private void TestDot(Vector3 a, Vector3 b)
{
// 计算 a、b 点积结果
float result = Vector3.Dot(a, b);
// 通过向量直接获取两个向量的夹角(默认为 角度), 此方法范围 [0 - 180]
float angle = Vector3.Angle(a, b);
// 计算 a、b 单位向量的点积,得到夹角余弦值,|a.normalized|*|b.normalized|=1;
result = Vector3.Dot(a.normalized, b.normalized);
// 通过反余弦函数获取 向量 a、b 夹角(默认为 弧度)
float radians = Mathf.Acos(result);
// 将弧度转换为 角度
angle = radians * Mathf.Rad2Deg;
}
//叉乘
private void TestCross(Vector3 a, Vector3 b)
{
//计算向量 a、b 的叉积,结果为 向量
Vector3 c = Vector3.Cross(a, b);
// 通过反正弦函数获取向量 a、b 夹角(默认为弧度)
float radians = Mathf.Asin(Vector3.Distance(Vector3.zero,
Vector3.Cross(a.normalized, b.normalized)));
float angle = radians * Mathf.Rad2Deg;
// 判断顺时针、逆时针方向,是在 2D 平面内的,所以需指定一个平面,
//下面以X、Z轴组成的平面为例 , (Y 轴为纵轴),
// 在 X、Z 轴平面上,判断 b 在 a 的顺时针或者逆时针方向,
if (c.y > 0)
{
// b 在 a 的顺时针方向
}
else if (c.y == 0)
{
// b 和 a 方向相同(平行)
}
else
{
// b 在 a 的逆时针方向
}
}
// 获取两个向量的夹角 Vector3.Angle 只能返回 [0, 180] 的值
// 如真实情况下向量 a 到 b 的夹角(80 度)则 b 到 a 的夹角是(-80)
// 通过 Dot、Cross 结合获取到 a 到 b, b 到 a 的不同夹角
private void GetAngle(Vector3 a, Vector3 b)
{
Vector3 c = Vector3.Cross(a, b);
float angle = Vector3.Angle(a, b);
// b 到 a 的夹角
float sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(a.normalized, b.normalized)));
float signed_angle = angle * sign;
Debug.Log("b -> a :" + signed_angle);
// a 到 b 的夹角
sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(b.normalized, a.normalized)));
signed_angle = angle * sign;
Debug.Log("a -> b :" + signed_angle);
}
}