一、向量的减法
①获取两个物体之间的距离(使用向量的模判断)
注意:Unity3D中的模可以直接使用向量的magnitude属性直接获得,如果不需要开平方根,可以使用向量的sqrMagnitude获得,这样,在一些不需要直接获取向量的模的时候可以减少运算量,因为平方根比较消耗计算时间。
/***
*
* Title: 第16章 3D数学
* Description:
* 功能:向量的减法
* Date: 2019
* Version: 1.0
* Modify Recorder:
*
*/
using UnityEngine;
using System.Collections;
public class Demo1 : MonoBehaviour {
public Transform traOther; //其他物体
private float _FloCloseDistance=5.0F; //设定限制接近的最小距离
void Update ()
{
if (traOther)
{
//使用向量减法( other.position - transform.position)获得两个对象之间的向量
var sqrLen = (traOther.position - transform.position).sqrMagnitude;
// 使用sqrMagnitude取代Magnitude来计算距离,提高运算效率
if (sqrLen < _FloCloseDistance * _FloCloseDistance)
{
print("其他物体太接近我了!");
}
else {
print("其他物体距离很远,目前很安全!");
}
}
}
}
②获取两个物体之间的距离(可以使用Unity向量类中的Distance(Vector3 a,Vector3 b)函数 )
/// <summary>
/// 获取到两个物体之间的距离
/// </summary>
/// <param name="targetObj">目标对象</param>
/// <param name="needMoveObj">需要移动的对象</param>
/// <returns></returns>
public float GetDistance(Transform targetObj,Transform needMoveObj,int Method=1)
{
float distance=0;
if (targetObj!=null && needMoveObj!=null)
{
switch (Method)
{
case 1:
distance = Vector3.Distance(targetObj.position, needMoveObj.position);
break;
case 2:
////获取到模的平方
//distance = (targetObj.position - needMoveObj.position).sqrMagnitude;
//获取到模的长度(消耗资源)
distance = (targetObj.position - needMoveObj.position).magnitude;
break;
default:
break;
}
}
return distance;
}
二、向量的加法
两个向量的维数必须相同,才能够相加减。
意义:向量a加向量b解释为:平移向量,使向量a的头连接向量b的尾,接着从a的尾向b的头画出一个向量(也叫三角形法则)
三、对向量进行单位化 (获取方向)
意义:只关心向量方向而不关心大小,比如飞机的朝向,某个面的法线朝向等。
单位向量就是大小为1的向量,它经常也被称为标准化向量、法线(Normal)或者归一化
单位化向量=向量/向量的模(且向量的模不等于0),可以使用Unity中的normalized属性或者Normalize()函数将向量单位化
Vector3 goNormalVec1 = Vector3.Normalize(gameObject.transform.position);
Vector3 goNormalVec2 = gameObject.transform.position.normalized;
Debug.Log("Vector3.Normalize方法物体的单位向量=" + goNormalVec1);
Debug.Log("normalized属性物体的单位向量=" + goNormalVec2);
四、向量与标量相乘(实现移动)
向量乘以标量K的效果是以因子|K|缩放向量的长度;如若果K<0,则向量除了做缩放操作外还使得向量方向倒转。
/***
*
* Title: 第16章 3D数学
*
* Description:
* 功能:向量与标量的乘法
*
* Date: 2019
* Version: 1.0
* Modify Recorder:
*
*/
using UnityEngine;
using System.Collections;
public class Demo2 : MonoBehaviour
{
public Vector3 speedDirection; //速度
public float speedScale=1F; //加速比率
void Update ()
{
gameObject.transform.position += speedDirection * speedScale*Time.deltaTime;
}
}
/// <summary>
/// 移动到目标点(跟随目标)
/// </summary>
/// <param name="targetObj">目标对象</param>
/// <param name="needMoveObj">需要移动的对象</param>
public void MoveToTargetPostion(Transform targetObj,Transform needMoveObj,float moveSpeed=0.5F)
{
if (targetObj!=null && needMoveObj != null && moveSpeed>=0)
{
//先计算二者方向
Vector3 dir = (targetObj.position - needMoveObj.position).normalized;
//物体从当前位置移动到目标位置
needMoveObj.position += dir * Time.deltaTime * speed;
}
}
五、向量的乘法
①向量的点乘
意义:点乘的计算结果给出了两个向量的相似程度,该相似度反映在两个向量之间的夹角上;
点乘结果越大,两个向量越接近;
点乘公式:a.b=||a|||b||cosθ==> θ = arccos(a·b)
如果只需知道a和b的夹角类型而不用知道该夹角的确切值,可以只根据所求出点乘结果的符号来判断
即a.b>0方向基本相同 a.b=0 a和b正交,相互垂直
//测试点积
private void TestDot(Vector3 a,Vector3 b)
{
//计算a,b点积结果
float result = Vector3.Dot(a,b);
Debug.Log("计算a,b点积结果="+result);
//通过向量直接获取两个向量的夹角(默认是角度)该方法范围是[0-180]
float angle = Vector3.Angle(a,b);
Debug.Log("通过向量计算a,b向量夹角=" + angle);
//计算a、b单位向量的点积,得到夹角余弦值|a.normalized|*|b.normalized|=1
result = Vector3.Dot(a.normalized,b.normalized);
Debug.Log("计算a,b单位向量的点积得到的余弦值=" + result);
//通过反余弦函数获取向量a、b夹角(默认是弧度)
float radians = Mathf.Acos(result);
Debug.Log("反余弦计算a,b夹角=" + radians);
//将弧度转换为角度
angle = radians * Mathf.Rad2Deg;
Debug.Log("计算反余弦计算a,b角度=" + angle);
}
/***
*
* Title:
* 第16章 3D数学
*
* Description:
* 功能:
* 学习向量的“点乘”
* 估算两个游戏对象的夹角角度。
*
* Date: 2017
*
* Version: 1.0
*
* Modify Recorder:
*
*/
using UnityEngine;
using System.Collections;
public class Demo3: MonoBehaviour {
public Transform TraOther; //其他物体的方位
private Vector3 _VecForward; //前方
private Vector3 _VecToOther; //其他方向
void Update () {
if (TraOther){
//使用TransformDirection把当前对象的正面朝向从局部坐标系转换到世界坐标系下,使得该向
//量与其他对象的位置向量在世界坐标系下统一
//Vector3.forward表示该对象当前的正方向向量
_VecForward = transform.TransformDirection(Vector3.forward);
//使用向量减法获得其他对象到当前对象之间的向量
_VecToOther = TraOther.position - transform.position;
//使用点乘计算结果的符号来判断其他对象是否在当前对象的后方
if (Vector3.Dot(_VecForward, _VecToOther) > 0)
{
print("其他对象在我前方!");
}
else
{
print("其他对象在我后方。");
}
}
}
}
/***
*
* Title:
* 第16章 3D数学
*
* Description:
* 功能:
* 学习向量的“点乘”
* 计算两个游戏对象的确切夹角角度。
*
* Date: 2017
*
* Version: 1.0
*
* Modify Recorder:
*
*/
using UnityEngine;
using System.Collections;
public class Demo4: MonoBehaviour {
public Transform TraTarget; //目标
private Vector3 _VecTargetDir;
private Vector3 _VecForward;
private float _FloAngle;
/* 当对象的朝向与目标对象夹角小于5时,打印“视线靠近了”信息 */
void Update () {
//使用向量减法获得当前对象与目标对象之间的向量
_VecTargetDir = TraTarget.position - transform.position;
//当前对象的正方向向量
_VecForward = transform.forward;
//求出targetDir和forward向量之间的夹角值
_FloAngle = Vector3.Angle(_VecTargetDir, _VecForward);
//判断该夹角是否小于5
if (_FloAngle < 5.0)
{
print("视线靠近了!");
}
else {
print("视线没有靠近。");
}
}
}
②向量的叉乘
意义:叉乘计算的结果是向量,该向量垂直于原来的两个向量
Vector3 normal = Vector3.Cross (fromVector,toVector);
//叉乘求出法线向量
angle *= Mathf.Sign (Vector3.Dot(normal,upVector));
//求法线向量与物体上方向向量点乘,结果为1或-1,修正旋转方向
计算出平面的法向量
Vector3 side1=b-a;
Vector3 side2=c-a;
Vector3 Normal=Vector3.Cross(side1,side2);
Normal.Normalize();
//叉乘
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)
{
Debug.Log(" b 在 a 的顺时针方向");
}
else if (c.y == 0)
{
Debug.Log(" b 和 a 方向相同(平行)");
}
else
{
Debug.Log(" 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);
}
注意:本内容参考:《Unity3D/2D游戏开发从0到1》第16章
http://www.manew.com/youxizz/2982.html