一、向量Vector的意义
Unity中表示出来的Vector,其实际意义可以是位置,也可以是表示一个向量
二、向量数学
1.向量模长
两个点决定一个向量,向量的模长就是两个点的距离,也就是向量的实际长度。
计算公式
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(5, 1, 5);
Vector3 AB = B - A;
Vector3 BA = A - B;
print(AB.magnitude);
Vector3 C = new Vector3(5,6,7);
print(C.magnitude);
Vector3.Distance(A, B);
Vector3.magntiude计算的是传入向量到原点距离,所以要传入的是做差后的向量。
Vector3.Distance计算的是两个点之间的距离,传入两点即可。
Vector3.Distance(A,B)=(B-A).magntiude
2.单位向量
计算公式
cs
print(AB.normalized);
print(AB / AB.magnitude);
3.向量加减
数学原理 向量相加,首位相连 。向量相减,头连头,减后尾指前尾。
Vector3 直接相加减就可以实现
4.向量乘除标量
实际效果是模型各轴向都缩小或者放大了n倍,导致的是模型被放大了n的3次方倍数。
cs
this.transform.localScale *= 2;
this.transform.localScale /= 2;
5.向量偏移的瞬时跟随
cs
public float zOffect = 4;
public float yOffect = 7;
public float xOffect = 0;
public Transform target;
void Update()
{
this.transform.position = target.position +Vector3.up*yOffect+-Vector3.forward*zOffect;
this.transform.LookAt(target);
}
只用各单位向量的位移偏移和LookAa函数即可实现。
用于摄像机,可以让摄像机以固定视角跟踪角色
6.向量点乘
数学公式 A点乘B =Ax*Bx+Ay*By+Az*Bz
向量 点乘 向量=标量,这个标量可以判断两个向量之间的夹角。
点乘结果 >0 两个向量夹角为锐角,点乘结果=0 两个向量夹角为直角,点乘结果 <0 两个向量夹角为钝角。可以用来判断敌方的位置。
cs
Transform player;
Transform enemy;
Vector3 toEnemy = enemy.position - player.position;
float dot = Vector3.Dot(player.forward, toEnemy.normalized);
if (dot > 0)
Debug.Log("敌人在前方");
else if (dot < 0)
Debug.Log("敌人在后方");
else
Debug.Log("敌人在正侧方");
函数中传入两个向量,用两个向量的单位向量去判断。
7、判断敌人的方位
原理就是点乘后的结果去判断。更简单的函数是Vector3.Angle()
Vector3.Angle()内部先点乘后转变为角度。Angle是一侧的度数,实际是单侧总和。
往往是在一个距离值,一个角度值。去判断敌人在不在范围内。
cs
if( Vector3.Distance(this.transform.position, B.transform.position) <= 5 &&
Vector3.Angle(this.transform.forward, B.transform.position - this.transform.position) <= 22.5f)
{
print("发现入侵者");
}
示例代码,敌方在半径五米,45度范围内都可以探测到。
8、向量叉乘
数学公式
向量A叉乘向量B=(YaZb-ZaYb,XaZb-ZaXb,XaYb-XbYa)
叉乘的几何意义 计算得到的向量是即垂直于向量A,也垂直于向量B。即垂直于AB平面的一个向量。
A叉乘B=-(B叉乘A)
假设向量A和B都在x z平面上 ,叉乘结果是y大于0 证明 B在A右侧,y小于0 证明 B在A左侧。
cs
Vector3.Cross(A.position, B.position)
Vector3 C = Vector3.Cross(B.position, A.position);
if (C.y > 0)
{
print("A在B的右侧");
}
else
{
print("A在B的左侧");
}
9、判断物体方位
判断一个物体B在另一个物体A的位置 左上,左下。右上,右下
cs
public Transform A;
public Transform B;
private float dotResult;
private Vector3 crossResult;
dotResult = Vector3.Dot(A.forward, B.position - A.position);
crossResult = Vector3.Cross(A.forward, B.position - A.position);
//判断前后
if (dotResult >= 0 )
{
//右侧
if(crossResult.y >= 0)
{
print("右前");
}
//左侧
else
{
print("左前");
}
}
else
{
//右侧
if (crossResult.y >= 0)
{
print("右后");
}
//左侧
else
{
print("左后");
}
}
寻找敌方,在自身左20度角,右30度角,5米半径范围内。
cs
if( Vector3.Distance(A.position, B.position) <= 5 )
{
if( crossResult.y >= 0 && Vector3.Angle(A.forward, B.position - A.position) <= 30 ||
crossResult.y < 0 && Vector3.Angle(A.forward, B.position - A.position) <= 20)
{
print("发现入侵者");
}
}
10、向量的插值运算
向量有Lerp和Slerp。Lerp是线性运动,Slerp是环形运动。
向量的插值是直接以xyz进行的,不用像Mathf中Lerp写三次。
11、摄像机跟随
cs
public Transform A;
public Transform camera;
public float offsetx = 0;
public float offsety = 7;
public float offsetz = -4;
public Vector3 pos;
public Vector3 nowPos;
public Vector3 startPos;
public float time;
pos = A.position + A.forward * offsetz + A.right * offsetx + A.up * offsety;
camera.position = Vector3.Lerp(camera.position, pos, Time.deltaTime);
if (A.position != nowPos)
{
time = 0;
pos = A.position + A.forward * offsetz + A.right * offsetx + A.up * offsety;
startPos = camera.position;
}
time += Time.deltaTime;
camera.position = Vector3.Lerp(startPos, nowPos, time);
三、注意
向量,点乘 叉乘 都是物体面单位向量,和敌方物体做差后的向量
点乘是一个值,叉乘是一个向量,点乘判断前后,叉乘判断左右。Angle方法得到角度。