Unity基础【唐老狮】(一)3D数学基础,向量
2022-05-28 本文已影响0人
Die时而动
Unity基础
概述&个人总结
基础知识点
3D数学-基础
- 基础数学函数
- 插值运算Lerp:根据系数输出中间值
- 先快后慢接近最终值
- 匀速到达最终值
#region 知识点四 Mathf中的常用方法——一般不停计算 //插值运算 - Lerp //Lerp函数公式 //result = Mathf.Lerp(start, end, t); //t为插值系数,取值范围为 0~1 //result = start + (end - start)*t //插值运算用法一 //每帧改变start的值——变化速度先快后慢,位置无限接近,但是不会得到end位置 start = Mathf.Lerp(start, 10, Time.deltaTime); //插值运算用法二 //每帧改变t的值——变化速度匀速,位置每帧接近,当t>=1时,得到结果 time += Time.deltaTime; result = Mathf.Lerp(start, 10, time); #endregion
- 三角函数
- 角度和弧度
- Mathf.Rad2Deg
- Mathf.Deg2Rad
- 三角函数
- 三角函数曲线
- 反三角函数
- Asin,Acos
- 练习:物体曲线移动
- 角度和弧度
- 坐标系
- 世界坐标系
- 物体坐标系
- 屏幕坐标系
- 视口坐标系
- 坐标转换
- Camera.main
#region 知识点一 世界坐标系 //目前学习的和世界坐标系相关的 //this.transform.position; //this.transform.rotation; //this.transform.eulerAngles; //this.transform.lossyScale; //修改他们 会是相对世界坐标系的变化 #endregion #region 知识点二 物体坐标系 //相对父对象的物体坐标系的位置 本地坐标 相对坐标 //this.transform.localPosition; //this.transform.localEulerAngles; //this.transform.localRotation; //this.transform.localScale; //修改他们 会是相对父对象物体坐标系的变化 #endregion #region 知识点三 屏幕坐标系 //Input.mousePosition //Screen.width; //Screen.height; #endregion #region 知识点四 视口坐标系 //摄像机上的 视口范围 #endregion #region 坐标转换相关 //世界转本地 //this.transform.InverseTransformDirection //this.transform.InverseTransformPoint //this.transform.InverseTransformVector //本地转世界 //this.transform.TransformDirection //this.transform.TransformPoint //this.transform.TransformVector //世界转屏幕 //Camera.main.WorldToScreenPoint //屏幕转世界 //Camera.main.ScreenToWorldPoint //世界转视口 //Camera.main.WorldToViewportPoint //视口转世界 //Camera.main.ViewportToWorldPoint //视口转屏幕 //Camera.main.ViewportToScreenPoint //屏幕转视口 //Camera.main.ScreenToViewportPoint;
3D数学-向量
- 向量模长和单位向量
- 向量基础
- 向量模长magnitude
- 单位向量normalized
public class Lesson4 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 向量
//三维向量 - Vector3
//Vector3有两种几何意义
//1.位置 —— 代表一个点
print(this.transform.position);
//2.方向 —— 代表一个方向
print(this.transform.forward);
print(this.transform.up);
Vector3 v = new Vector3(1, 2, 3);
Vector2 v2 = new Vector2(1, 2);
#endregion
#region 知识点二 两点决定一向量
//A和B此时 几何意义 是两个点
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(5, 1, 5);
//求向量
//此时 AB和 BA 他们的几何意义 是两个向量
Vector3 AB = B - A;
Vector3 BA = A - B;
#endregion
#region 知识点三 零向量和负向量
print(Vector3.zero);
print(Vector3.forward);
print(-Vector3.forward);
#endregion
#region 知识点四 向量的模长
//Vector3中提供了获取向量模长的成员属性
//magnitude
print(AB.magnitude);
Vector3 C = new Vector3(5, 6, 7);
print(C.magnitude);
print(Vector3.Distance(A, B));
#endregion
#region 知识点五 单位向量
//Vector3中提供了获取单位向量的成员属性
//normalized
print(AB.normalized);
print(AB / AB.magnitude);
#endregion
}
//总结
//1.Vector3这边变量 可以表示一个点 也可以表示一个向量 具体表示什么 是根据我们的具体需求和逻辑决定
//2.如何在Unity里面得到向量 重点减起点 就可以得到向量 点C也可以代表向量 代表的就是 OC向量 O是坐标系原点
//3.得到了向量 就可以利用 Vector3中提供的 成员属性 得到模长和单位向量
//4.模长相当于可以得到 两点之间的距离 单位向量 主要是用来进行移动计算的 它不会影响我们想要的移动效果
```
- 向量加减乘除
- 练习:使摄像机始终保持在物体后面一段距离
- 注意摄像机移动放在LateUpdate()生命周期函数内
- 练习:使摄像机始终保持在物体后面一段距离
- 向量点乘
- 点乘公式:结果是标量
- 点乘几何意义
- 带符号投影的长度
- 使用点乘
- 判断对象方位
- 投影为正在前方,投影为负在后方
- 计算两个向量之间的夹角
- 单位向量点乘结果为cos夹角
- 用反三角函数得出弧度
- 弧度换算角度
- 判断对象方位
- 代码
#region 补充知识 调试画线 //画线段 //前两个参数 分别是 起点 终点 //Debug.DrawLine(this.transform.position, this.transform.position + this.transform.forward, Color.red); //画射线 //前两个参数 分别是 起点 方向 //Debug.DrawRay(this.transform.position, this.transform.forward, Color.white); #endregion #region 知识点一 通过点乘判断对象方位 //Vector3 提供了计算点乘的方法 Debug.DrawRay(this.transform.position, this.transform.forward, Color.red); Debug.DrawRay(this.transform.position, target.position - this.transform.position, Color.red); //得到两个向量的点乘结果 //向量 a 点乘 AB 的结果 float dotResult = Vector3.Dot(this.transform.forward, target.position - this.transform.position); if( dotResult >= 0 ) { print("它在我前方"); } else { print("它在我后方"); } #endregion #region 知识点二 通过点乘推导公式算出夹角 //步骤 //1.用单位向量算出点乘结果 dotResult = Vector3.Dot(this.transform.forward, (target.position - this.transform.position).normalized); //2.用反三角函数得出角度 print("角度-" + Mathf.Acos(dotResult) * Mathf.Rad2Deg); //Vector3中提供了 得到两个向量之间夹角的方法 print("角度2-" + Vector3.Angle(this.transform.forward, target.position - this.transform.position)); #endregion
- 练习:检测前方45度角,5米距离内的物体
- 手动根据算
- 使用API
- Vector3.Distance
- Vector3.Angle
- 向量叉乘
- 叉乘公式
- 叉乘几何意义
- 垂直于平面的法向量
- 使用叉乘
- 判断两个向量之间的左右位置关系
Vector3 C = Vector3.Cross(B.position, A.position); if (C.y > 0) { print("A在B的右侧"); } else { print("A在B的左侧"); }
- 练习
- 判断大致方位
- 判断具体方位左20右30度距离5m
public class DetectDirction : MonoBehaviour { //- 判断大致方位 //- 判断具体方位及距离 public Transform cube; private Vector3 myDir; private Vector3 cube2me; private float dot; private Vector3 cross; // Start is called before the first frame update void Start() { myDir = this.transform.forward; } // Update is called once per frame void Update() { cube2me = cube.transform.position - this.transform.position; //判断大致方位 dot = Vector3.Dot(myDir, cube2me); cross = Vector3.Cross(myDir, cube2me); if (dot > 0 && cross.y > 0) { Debug.Log("在右上"); } if (dot < 0 && cross.y < 0) { Debug.Log("在左下"); } if (dot > 0 && cross.y < 0) { Debug.Log("在左上"); } if (dot < 0 && cross.y > 0) { Debug.Log("在右下"); } //判断具体方位左20右30度距离5m float distance = Vector3.Distance(this.transform.position, cube.position); //float angle = Vector3.Angle(myDir, cube2me); float angle = Mathf.Acos(Vector3.Dot(this.transform.forward.normalized, cube2me.normalized)) * Mathf.Rad2Deg; Debug.Log("角度" + angle); if (distance < 5 && (angle < 20 && cross.y < 0) || (angle < 30 && cross.y > 0)) { Debug.Log("侦测到左20右30度距离5m的方块"); } } }
- 向量插值运算
- 线性插值
- 变速直线运动
- 匀速直线运动
- 球形插值
- 变速弧线运动
- 匀速弧线运动
- 练习题
- 设置摄像机变速跟随
- 模拟太阳升降
- 给一定角度,突出立体下哪一个平面
public class CameraFollow : MonoBehaviour { //摄像机跟随 public float zOffect = 4; public float yOffect = 7; public Transform target; //变速跟随 private Vector3 targetCameraPos; public float moveSpeed = 1; //匀速跟随 private float time = 0; private Vector3 startPos; //模拟太阳 public Transform sun; // Start is called before the first frame update void Start() { //初始化摄像机位置 this.transform.position = targetCameraPos = target.position - target.forward * zOffect + target.up * yOffect; } // Update is called once per frame void Update() { ////变速跟随 ///targetCameraPos = target.position - target.forward * zOffect + target.up * yOffect; //this.transform.position = Vector3.Lerp(this.transform.position, targetCameraPos, Time.deltaTime * moveSpeed); //this.transform.LookAt(target); //匀速跟随 if (targetCameraPos != target.position - target.forward * zOffect + target.up * yOffect) { targetCameraPos = target.position - target.forward * zOffect + target.up * yOffect; startPos = this.transform.position; Debug.Log("终点改变"); time = 0; } time += Time.deltaTime;//默认一秒 this.transform.position = Vector3.Lerp(startPos, targetCameraPos, time * moveSpeed); this.transform.LookAt(target); //模拟太阳 sun.position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 + Vector3.up * 0.1f, time * moveSpeed); } }
- 线性插值