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

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

3.向上取整-CeilToInt

float f = 1.3f;
int i = (int)f;
print(i);
print(Mathf.CeilToInt(f));

4.向下取整-FloorToInt

print(Mathf.FloorToInt(9.6F));

5.钳制函数-Clamp

print(Mathf.Clamp(10, 11, 20));//11 比最小还小取最小
print(Mathf.Clamp(21, 11, 20));//20 比最大还大取最大
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 

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

9.四舍五入-RoundToInt

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

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

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

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

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

12.判断正负数-Sign

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

4.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);

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.弧度转角度

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

4.角度转弧度 

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

2.三角函数

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

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

 3.反三角函数

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

rad = Mathf.Asin(0.5f);
print(rad*Mathf.Rad2Deg);//30

rad = Mathf.Acos(0.5f);
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.世界坐标系 

原点:世界的中心点

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

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

2.物体坐标系

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

​轴向:

​物体右方为 x 轴正方向

​物体上方为 y 轴正方向

​物体前方为 z 轴正方向

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

3.屏幕坐标系

原点:屏幕左下角

​轴向:

​向右为 x 轴正方向

​向上为 y 轴正方向

最大宽高:

Screen.width

Screen.height

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

4.视口坐标系 

摄像机上的 视口范围 

5.坐标转换相关 

1.世界转本地
  this.transform.InverseTransformDirection;
  this.transform.InverseTransformPoint;
  this.transform.InverseTransformVector;
 
2.本地转世界
  this.transform.TransformDirection;
  this.transform.TransformPoint;
  this.transform.TransformVector;
 
3.世界转屏幕
  Camera.main.WorldToScreenPoint
  屏幕转世界
  Camera.main.ScreenToWorldPoint
        
4.世界转视口
  Camera.main.WorldToViewportPoint
  视口转世界
  Camera.main.ViewportToWorldPoint
 
5.视口转屏幕
  Camera.main.ViewportToScreenPoint
  屏幕转视口
  Camera.main.ScreenToViewportPoint

4.向量模长和单位向量

1.向量

三维向量-Vector3

Vector3有两种几何意义

1.位置——代表一个点

print(this.transform.position);

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

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

2.两点决定一向量

//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;

3.零向量和负向量

print(Vector3.zero);
 
print(Vector3.forward);
print(-Vector3.forward);

4.向量的模长

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

5.单位向量

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

5.向量加减乘除

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

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

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

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

6.向量点乘 

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

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

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

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

1.调试画线 

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

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

//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("它在我后方");

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

步骤:
1.用单位向量算出点乘结果
dotResult = Vector3.Dot(this.transform.forward, target.position - this.transform.position);
2.用反三角函数得出角度
print("角度" + Mathf.Acos(dotResult)*Mathf.Rad2Deg);
 
Vector3中提供了 得到两个向量之间夹角的方法
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中每帧执行一次

public Transform target;    // 目标物体位置
public Transform A;         // 先快后慢移动到 Target
public Transform B;         // 匀速运动到 Target

private Vector3 nowTarget;  // 当前 B 的位置

private Vector3 startPos;   // 每次运行时 B 的起始位置
private float   time;

// Start is called before the first frame update
private void Start() {
    startPos = B.position;
}

// Update is called once per frame
private void Update() {
    // result = start + (end - start) * t

    // 1.先快后慢 每帧改变start位置 位置无限接近 但不会得到end位置
    A.position = Vector3.Lerp(A.position, target.position, Time.deltaTime);

    // 2.匀速 每帧改变时间  当t>=1时 得到结果
    // 这种匀速移动 当time>=1时  我改变了 目标位置后  它会直接瞬移到我们的目标位置
    if (nowTarget != target.position) {
        nowTarget = target.position;
        time      = 0;
        startPos  = B.position;
    }
    time       += Time.deltaTime;
    B.position =  Vector3.Lerp(startPos, nowTarget, time);
}

2.球形插值

弧形移动位置

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

position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 + Vector3.up * 0.1f, time * 0.01f);

猜你喜欢

转载自blog.csdn.net/weixin_45274937/article/details/126747317
今日推荐