赞
踩
一、向量的减法
①获取两个物体之间的距离(使用向量的模判断)
注意: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
https://blog.csdn.net/yupu56/article/details/53609028
https://blog.csdn.net/Game_jqd/article/details/78908152
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。