• Unity基础01——3D数学


    1.数学计算公共类Mathf

    1.Mathf和Math 

    Math是C#中封装好的用于数学计算的工具类——位于system命名空间中

    Mathf是Unity中封装好的用于数学计算的工具结构体——位于UnityEngine命名空间中

    他们都是提供来用于进行数学相关计算的

    2.他们的区别

    Mathf 和 Math中的相关方法几乎一样

    Math 是C#自带的工具类 主要就是提供一些数学相关的计算方法

    Mathf 是Unity专门封装的,不仅包含Math中的方法,还多了一些适用于游戏开发的方法

    所以我们在进行unity游戏开发时

    使用Mathf中的方法用于数学计算即可

    3.Mathf中的常用方法——一般计算一次 

    1.Π-PI 

    print(Mathf.PI);

    2.取绝对值-Abs

    1. print(Mathf.Abs(-10));
    2. print(Mathf.Abs(-20));
    3. print(Mathf.Abs(1));

    3.向上取整-CeilToInt

    1. float f = 1.3f;
    2. int i = (int)f;
    3. print(i);
    4. print(Mathf.CeilToInt(f));

    4.向下取整-FloorToInt

    print(Mathf.FloorToInt(9.6F));

    5.钳制函数-Clamp

    1. print(Mathf.Clamp(10, 11, 20));//11 比最小还小取最小
    2. print(Mathf.Clamp(21, 11, 20));//20 比最大还大取最大
    3. print(Mathf.Clamp(15, 11, 20));//15 在两者之前取本身

    6.获取最大值-Max  

    print(Mathf.Max(1, 2, 3, 4, 5, 6, 7, 8));

    7.获取最小值-Min

    print(Mathf.Min(1, 2, 3, 4, 5, 6, 7, 8));

    8.一个数的n次幂-Pow 

    1. print("一个数的n次方" + Mathf.Pow(4, 2));//16
    2. print("一个数的n次方" + Mathf.Pow(2,3)); //8

    9.四舍五入-RoundToInt

    1. print("四舍五入" + Mathf.RoundToInt(1.3f));//1
    2. print("四舍五入" + Mathf.RoundToInt(1.5f));//2

    10.返回一个数的平方根-Sqrt

    1. print("返回一个数的平方根"+Mathf.Sqrt(4));//2
    2. print("返回一个数的平方根"+Mathf.Sqrt(16));//4
    3. print("返回一个数的平方根"+Mathf.Sqrt(64));//8

    11.判断一个数是否是2的n次方-IsPowerOfTow

    1. print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(4));//true
    2. print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(8));//true
    3. print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(3));//false

    12.判断正负数-Sign

    1. print("判断正负数" + Mathf.Sign(0));//1
    2. print("判断正负数" + Mathf.Sign(10));//1
    3. print("判断正负数" + Mathf.Sign(-10));//-1

    4.Mathf中的常用方法——一般不停计算 

    1. 插值运算-Lerp
    2. Lerp函数公式
    3. result = Mathf。Lerp(start,end,t);
    4. t为插值系数,取值范围为0~1
    5. result = start + (end-start)*t
    6. 插值运算用法一
    7. 每帧改变start的值——变化先快后慢,位置无限接近,但是不会得到end位置
    8. start = Mathf.Lerp(start, 10, Time.deltaTime);
    9. 插值运算用法二
    10. 每帧改变t的值——变化速度匀速,位置每帧接近,当t>=1时,得到结果
    11. time += Time.deltaTime;
    12. result = Mathf.Lerp(start, 10, time);

    2.三角函数 

    1.弧度、角度相互转换 

    1.角度和弧度

    角度和弧度都是度量角的单位

    角度:1°

    弧度:1 radian

    圆一周的角度:360°

    圆一周的弧度:2Π radian 

    2.角度和弧度的转换关系

    Π rad = 180°

    1 rad = t.(180/TI)°=> 1 rad = 180 / 3.14 ≈ 57.3°

    1°= (Π / 180) rad => 1° = 3.14 / 180~ 0.01745 rad

    由此可以得出

    弧度*57.3=对应角度

    角度*0.01745=对应弧度 

    3.弧度转角度

    1. float rad = 1;
    2. float anger=rad*Mathf.Rad2Deg;
    3. print(anger);//57.29578

    4.角度转弧度 

    1. anger = 1;
    2. rad = anger * Mathf.Deg2Rad;
    3. print(rad);//0.01745329

    2.三角函数

    注意:Mathf中的三角函数,传入的参数需要时弧度值 

    1. print(Mathf.Sin(30 * Mathf.Deg2Rad));//0.5
    2. print(Mathf.Cos(60 * Mathf.Deg2Rad));//0.5

     3.反三角函数

    注意:反三角函数得到的结果是 正弦或者余弦值对应的弧度 

    1. rad = Mathf.Asin(0.5f);
    2. print(rad*Mathf.Rad2Deg);//30
    3. rad = Mathf.Acos(0.5f);
    4. print(rad * Mathf.Rad2Deg);//60

    4.总结 

    1.三角函数———Mathf.Sin(弧度)、Mathf.Cos(弧度)

    2.角度和弧度———Mathf.Rad2Deg、Mathf.Deg2Rad

    3.三角函数曲线——Sin和Cos函数曲线对于我们的意义

    4.反三角函数——Mathf.Asin(正弦值)、Mathf.Acos(余弦值) 

    3.坐标系 

    1.世界坐标系 

    原点:世界的中心点

    ​轴向:世界坐标系的三个轴向是固定的 

    1. 目前学习的和世界坐标系相关的
    2. this.transform.position; // 坐标
    3. this.transform.rotation; // 旋转角度
    4. this.transform.eulerAngles; // 欧拉角度
    5. this.transform.lossyScale; // 本地缩放大小

    2.物体坐标系

    原点:物体的中心点(建模时决定)

    ​轴向:

    ​物体右方为 x 轴正方向

    ​物体上方为 y 轴正方向

    ​物体前方为 z 轴正方向

    1. 相对父对象的物体坐标系的位置 本地坐标 相对坐标
    2. this.transform.localPosition;
    3. this.transform.localRotation;
    4. this.transform.localEulerAngles;
    5. this.transform.localScale;
    6. 修改他们 会是相对父对象物体坐标系的变化

    3.屏幕坐标系

    原点:屏幕左下角

    ​轴向:

    ​向右为 x 轴正方向

    ​向上为 y 轴正方向

    最大宽高:

    Screen.width

    Screen.height

    1. Input.mousePosition; // 鼠标位置
    2. Screen.width; // 屏幕宽
    3. Screen.height; // 屏幕高

    4.视口坐标系 

    摄像机上的 视口范围 

    5.坐标转换相关 

    1. 1.世界转本地
    2. this.transform.InverseTransformDirection;
    3. this.transform.InverseTransformPoint;
    4. this.transform.InverseTransformVector;
    5. 2.本地转世界
    6. this.transform.TransformDirection;
    7. this.transform.TransformPoint;
    8. this.transform.TransformVector;
    9. 3.世界转屏幕
    10. Camera.main.WorldToScreenPoint
    11. 屏幕转世界
    12. Camera.main.ScreenToWorldPoint
    13. 4.世界转视口
    14. Camera.main.WorldToViewportPoint
    15. 视口转世界
    16. Camera.main.ViewportToWorldPoint
    17. 5.视口转屏幕
    18. Camera.main.ViewportToScreenPoint
    19. 屏幕转视口
    20. Camera.main.ScreenToViewportPoint

    4.向量模长和单位向量

    1.向量

    三维向量-Vector3

    Vector3有两种几何意义

    1.位置——代表一个点

    print(this.transform.position);

    2.方向——代表一个方向

    1. print(this.transform.forward);
    2. print(this.transform.up);
    3. Vector3 v3 = new Vector3(1, 2, 3);
    4. Vector2 v2 = new Vector2(1, 2);

    2.两点决定一向量

    1. //A和B此时 几何意义是两个点
    2. Vector3 A = new Vector3(1, 2, 3);
    3. Vector3 B = new Vector3(5, 1, 5);
    4. //求向量
    5. //此时 AB和BA代表的 是两个向量
    6. Vector3 AB = B - A;
    7. Vector3 BA = A - B;

    3.零向量和负向量

    1. print(Vector3.zero);
    2. print(Vector3.forward);
    3. print(-Vector3.forward);

    4.向量的模长

    1. //Vector3中提供了获取向量模长的成员属性
    2. print(AB.magnitude);
    3. Vector3 C = new Vector3(5, 6, 7);
    4. print(C.magnitude);
    5. //Vector3.Distance(A, B);

    5.单位向量

    1. //Vector3中提供了获取单位向量的成员属性
    2. //normalized
    3. print(AB.normalized);
    4. print(AB/AB.magnitude);

    5.向量加减乘除

    1.向量加法——主要用于位置平移和向量计算

    2.向量减法——主要用于位置平移和向量计算

    3.向量乘除法——主要用于模长放大缩小

    1. #region 向量加法
    2. //this.transform.position+=new Vector3 (1,2,3);
    3. this.transform.Translate(Vector3.forward * 5);
    4. #endregion
    5. #region 向量减法
    6. //this.transform.position-=new Vector3 (1,2,3);
    7. this.transform.Translate(-Vector3.forward * 5);
    8. #endregion
    9. #region 向量乘除标量
    10. this.transform.localScale *= 2;
    11. this.transform.localScale /= 2;

    6.向量点乘 

    点乘可以得到一个向量在自己向量上投影的长度

    点乘结果>0两个向量夹角为锐角

    点乘结果=0两个向量夹角为直角

    点乘结果<0两个向量夹角为钝角

    1.调试画线 

    1. 在场景窗口显示,游戏窗口不显示
    2. 画线段
    3. 前两个参数 分别是 起点 终点
    4. Debug.DrawLine(this.transform.position, this.transform.position+this.transform.forward, Color.red);
    5. 画射线
    6. 前两个参数分别是 起点 方向
    7. Debug.DrawRay(this.transform.position, this.transform.forward, Color.white);

    2.通过点乘判断对象方位

    1. //Vector3 提供了计算点乘的方法
    2. Debug.DrawRay(this.transform.position, this.transform.forward, Color.red);
    3. Debug.DrawRay(this.transform.position, target.position-this.transform.position, Color.red);
    4. //得到两个向量的点乘结果
    5. //向量 a 点乘 AB 的结果
    6. float dotResult = Vector3.Dot(this.transform.forward, target.position - this.transform.position);
    7. if (dotResult >= 0)
    8. print("它在我前方");
    9. else
    10. print("它在我后方");

    3.通过点乘推导公式算出夹角

    1. 步骤:
    2. 1.用单位向量算出点乘结果
    3. dotResult = Vector3.Dot(this.transform.forward, target.position - this.transform.position);
    4. 2.用反三角函数得出角度
    5. print("角度" + Mathf.Acos(dotResult)*Mathf.Rad2Deg);
    6. Vector3中提供了 得到两个向量之间夹角的方法
    7. print("角度2" + Vector3.Angle(this.transform.forward, target.position - this.transform.position));

    7.向量叉乘 

    1.向量叉乘计算 

    print(Vector3.Cross(A.position, B.position));

    2.向量叉乘几何意义

    假设向量A和B都在XZ平面上

    向量A叉乘向量B

    y大于0 证明 B在A右侧

    y小于0 证明 B在A左侧

    8.向量插值运算 

    1.线性插值

    1.Vector3.Lerp(开始位置,结束位置,t) ;    t(0-1)和数学类中的插值运算原理一样

    2.快到慢

    开始位置的改变量先快后慢,无限接近结束位置

    开始位置=Vector3.Lerp(开始位置,结束位置,t) t和结束位置不改变

    3.匀速

    开始位置赋值给另一个变量A,A作为函数的第一个参数,改变t

    t+=Time.deltaTime;

    beginPos=Vector3.Lerp(A,结束位置,t);

    注意t大于等于1的时候 beginPos等于结束位置

    4.插值运算在Update中每帧执行一次

    1. public Transform target; // 目标物体位置
    2. public Transform A; // 先快后慢移动到 Target
    3. public Transform B; // 匀速运动到 Target
    4. private Vector3 nowTarget; // 当前 B 的位置
    5. private Vector3 startPos; // 每次运行时 B 的起始位置
    6. private float time;
    7. // Start is called before the first frame update
    8. private void Start() {
    9. startPos = B.position;
    10. }
    11. // Update is called once per frame
    12. private void Update() {
    13. // result = start + (end - start) * t
    14. // 1.先快后慢 每帧改变start位置 位置无限接近 但不会得到end位置
    15. A.position = Vector3.Lerp(A.position, target.position, Time.deltaTime);
    16. // 2.匀速 每帧改变时间 当t>=1时 得到结果
    17. // 这种匀速移动 当time>=1时 我改变了 目标位置后 它会直接瞬移到我们的目标位置
    18. if (nowTarget != target.position) {
    19. nowTarget = target.position;
    20. time = 0;
    21. startPos = B.position;
    22. }
    23. time += Time.deltaTime;
    24. B.position = Vector3.Lerp(startPos, nowTarget, time);
    25. }

    2.球形插值

    弧形移动位置

    Vector3.Slerp(开始位置,结束位置,t) ;t(0-1) 

    position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 + Vector3.up * 0.1f, time * 0.01f);
  • 相关阅读:
    驱动开发11-2 编写SPI驱动程序-点亮数码管
    JavaSE之多线程高级(死锁、线程等待和唤醒)
    已解决SyntaxError: invalid character ‘(‘ (U+FF08)
    kubernetes 概述
    网络原理 --- 传输层Ⅱ TCP协议中的确认应答,超时重传和连接管理
    JAVA面试题整理《微服务篇》一
    【scala】类的属性
    Python - FastAPI 实现 get、post 请求
    GBASE 8C——SQL参考6 sql语法(5)
    python编程从入门到实践2——列表
  • 原文地址:https://blog.csdn.net/weixin_45274937/article/details/126747317