2025Unity中的核心数学工具(一)详解(穿插Unity实战相关案例)

一、数学计算工具Mathf

1.math与mathf的区别

特性Mathf (Unity)Math (C#)
命名空间UnityEngineSystem
功能范围包含Math方法+游戏开发专用方法基础数学计算方法
适用场景Unity游戏开发通用C#应用程序

结论在Unity开发中,优先使用Mathf

2.Mathf常用方法详解

(1)基础常数

print(Mathf.PI); // 输出圆周率π

(2)取绝对值

print(Mathf.Abs(-10));  // 输出:10
print(Mathf.Abs(-20));  // 输出:20
print(Mathf.Abs(1));    // 输出:1

(3)取整运算

// 向上取整
float f = 1.3f;
print((int)f);                  // 输出:1(直接截断)
print(Mathf.CeilToInt(f));      // 输出:2(向上取整)
print(Mathf.CeilToInt(1.00001f)); // 输出:2

// 向下取整
print(Mathf.FloorToInt(9.6f));  // 输出:9

(4)数值限制

// 钳制函数 - 将数值限制在指定范围内
print(Mathf.Clamp(10, 11, 20));  // 输出:11(小于最小值)
print(Mathf.Clamp(21, 11, 20));  // 输出:20(大于最大值)
print(Mathf.Clamp(15, 11, 20));  // 输出:15(在范围内)

(5)极值计算

// 最大值
print(Mathf.Max(1, 2, 3, 4, 5, 6, 7, 8));  // 输出:8
print(Mathf.Max(1, 2));                    // 输出:2

// 最小值
print(Mathf.Min(1, 2, 3, 4, 545, 6, 1123, 123)); // 输出:1
print(Mathf.Min(1.1f, 0.4f));                     // 输出:0.4

(6)幂运算与平方根

// 幂运算
print("一个数的n次方" + Mathf.Pow(4, 2));  // 输出:16
print("一个数的n次方" + Mathf.Pow(2, 3));  // 输出:8

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

(7)四舍五入

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

(8)特殊判断函数

// 判断是否为2的n次方
print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(4));  // 输出:True
print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(8));  // 输出:True
print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(3));  // 输出:False
print("判断一个数是否是2的n次方" + Mathf.IsPowerOfTwo(1));  // 输出:True

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

3.插值运算

(1)Lerp函数原理

语法result = Mathf.Lerp(start, end, t)

等价公式result = start + (end - start) * t

参数说明:

start:起始值          end:目标值          t:插值系数(0~1) 

返回值:两个值之间按比例得到的过渡值

(2)两种常用用法

【1】每帧改变start值
void Update()
{
    // 变化速度先快后慢,无限接近目标值但不会完全到达
    start = Mathf.Lerp(start, 10, Time.deltaTime);
}

特点减速运动,永远达不到精确终点

【2】每帧改变t值
float time = 0;
float result = 0;

void Update()
{
    time += Time.deltaTime;
    // 匀速变化,当t≥1时到达终点
    result = Mathf.Lerp(start, 10, time);
}

特点匀速运动,可以精确到达终点

4.Unity——Lerp练习题

(1)题目

        使用Lerp在Unity实现一个物体向另外一个物体移动

(2)实现逻辑

方法一:减速运动

【1】首先创建两个物体:两个球体。创建一个脚本,并把脚本挂在在一个物体上

【2】实现代码逻辑

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class testmove : MonoBehaviour
{
    public Transform BlueObject;//代表蓝球   
    public float movespeed;//为了方便调节速度,我添加一个可以随时改变的量
    //脚本挂在红球上    this:指代红球
    private void Update()
    {
        Mathf.Lerp(this.transform.position.x, BlueObject.position.x, Time.deltaTime * movespeed);
        Mathf.Lerp(this.transform.position.y, BlueObject.position.y, Time.deltaTime * movespeed);
        Mathf.Lerp(this.transform.position.z, BlueObject.position.z, Time.deltaTime * movespeed);
    }
}

(3)效果展示

lerp移动减速

方法二:匀速运动

【1】同上

【2】实现代码逻辑

public class testmove : MonoBehaviour
{
    public Transform BlueObject;//代表蓝球   
    public float movespeed=1;//为了方便调节速度,我添加一个可以随时改变的量
    public Vector3 Temppos;//用于动态接受改变之后的红球坐标
    public float TimeCount = 0f;
    //脚本挂在红球上    this:指代红球
    private void FixedUpdate()//这里我函数名修改了(为了保证没有外界干扰而已,不影响结论)
    {
        TimeCount += Time.deltaTime;
        Temppos.x = Mathf.Lerp(this.transform.position.x, BlueObject.position.x, TimeCount * movespeed);
        Temppos.y = Mathf.Lerp(this.transform.position.y, BlueObject.position.y, TimeCount * movespeed);
        Temppos.z = Mathf.Lerp(this.transform.position.z, BlueObject.position.z, TimeCount * movespeed);
        this.transform.position = Temppos;
    }
}

【3】效果图

lerp匀速


二、三角函数

1.弧度与角度的相互转化

角度:         弧度:1 radian        圆一周的角度:360°        圆一周的弧度:2π radian
// 弧度转角度
float rad = 1;
float anger = rad * Mathf.Rad2Deg;
print(anger);

// 角度转弧度
anger = 1;
rad = anger * Mathf.Deg2Rad;
print(rad);

(1)Unity 中 Mathf.Rad2Deg 是一个常量(约等于 57.2958),用于将弧度转换为角度

(2)Mathf.Deg2Rad 是其倒数(约等于 0.01745),用于将角度转换为弧度

(3)转换公式:角度 = 弧度 × Mathf.Rad2Deg弧度 = 角度 × Mathf.Deg2Rad

2.三角函数的使用

(1)正弦函数(sin)

        Sin β = 角的对边 / 斜边                                                 Sin β = A / C
【1】正弦曲线

(2)余弦函数(cos)

        Cos β = 角的临边 / 斜边                                                 Cos β = B / C
【1】余弦曲线

【2】常用正弦余弦值

// 注意:Mathf中的三角函数相关函数,传入的参数需要是弧度值
print(Mathf.Sin(30 * Mathf.Deg2Rad));// 输出约0.5
print(Mathf.Cos(60 * Mathf.Deg2Rad));// 输出约0.5

(1)Unity 中的 Mathf.Sin() 和 Mathf.Cos() 函数必须传入弧度值,而不是角度值

3.反三角函数的使用

// 反三角函数得到的结果是正弦或者余弦值对应的弧度
rad = Mathf.Asin(0.5f);
print(rad * Mathf.Rad2Deg); // 输出30
rad = Mathf.Acos(0.5f);
print(rad * Mathf.Rad2Deg); // 输出60

(1)反三角函数是三角函数的逆运算:Asin(x) 求的是正弦值为 x 的角度(弧度形式)

(2)反三角函数的返回值是弧度,需要转换为角度才能得到我们直观理解的度数

(3)输入值范围限制:Asin 和 Acos 的参数必须在 [-1, 1] 范围内,否则会返回 NaN Not a Number(非数字)的缩写

4.Unity——三角函数练习题

1.题目

        实现一个物体按曲线移动(正弦或者余弦曲线)

2.实现逻辑

(1)首先实现一个物体水平方向匀速直线运动

(2)然后实现这个物体垂直方向做上下运动(sinx的-1~1之间变化)的运动

(3)代码实现

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class test2TriFun : MonoBehaviour
{
    public float zSpeed=2;//直线速度
    public float ySpeed=1;//竖直方向的速度
    public float yLength = 1;//三角函数的幅度大小
    public float TimeCount = 0;
    //3.两个运动和起来就是曲线运动
    private void Update()
    {
        TimeCount += Time.deltaTime;
        //1.首先得让物体沿着一个轴方向(这里我选Z轴)做匀速直线运动
        this.transform.Translate(Vector3.forward*zSpeed*Time.deltaTime);
        //2.然后沿着竖直(Y轴)或者另外一个轴(X轴)【这里我选Y轴】做上下运动
        this.transform.Translate(Vector3.up * yLength *Time.deltaTime* Mathf.Sin(TimeCount* ySpeed));
    }
}

3.效果展示

三角函数曲线运动

三、坐标系

1.世界坐标系(World Coordinate System)

 //目前学习的和世界坐标系相关的
 this.transform.position;
 this.transform.rotation;
 this.transform.eulerAngles;
 this.transform.lossyScale;
// 修改他们 会是相对世界坐标系的变化

(1)transform.position物体在世界坐标系中的三维坐标(x,y,z),表示物体相对于世界原点的位置

(2)transform.rotation物体在世界坐标系中的旋转(四元数形式),描述物体的朝向

(3)transform.eulerAngles物体在世界坐标系中的旋转(欧拉角形式,单位:度),更直观(如 x 轴旋转 90° 表示绕世界 x 轴翻转)。

(4)transform.lossyScale物体的 “损失缩放”,本质是物体在世界坐标系中的最终缩放比例(考虑了父物体的缩放叠加)。例如:一个子物体的 localScale 是 (2,2,2),而它的父物体 localScale 是 (0.5,0.5,0.5),那么子物体的 lossyScale 就是 (1,1,1)

2.物体坐标系(Local Coordinate System)

核心:物体坐标系是相对于父物体的局部坐标系。当一个物体成为另一个物体的子物体时,它的位置、旋转、缩放都会以父物体的坐标系为基准。

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

(1)transform.localPosition物体相对于父物体原点的位置。若没有父物体,则等同于 position

(2)transform.localEulerAngles物体相对于父物体的旋转(欧拉角)。例如,父物体旋转 90° 后,子物体的 localEulerAngles 为(0,0,0)表示与父物体朝向一致。

(3)transform.localRotation物体相对于父物体的旋转(四元数形式)。

(4)transform.localScale物体相对于父物体的缩放比例。例如,父物体缩放为(2,2,2),子物体 localScale 为(0.5,0.5,0.5),则子物体在世界坐标系中的实际缩放为(1,1,1)。

        Tips:子物体的变换会跟随父物体

3.屏幕坐标系(Screen Coordinate System)

(1)概念

        屏幕坐标系是 2D 坐标系,以屏幕左下角为原点(0,0),右上角为(Screen.width, Screen.height),单位是像素。主要用于处理鼠标、触摸等屏幕交互。

Input.mousePosition
Screen.width;
Screen.height;

【1】Input.mousePosition鼠标在屏幕坐标系中的位置(x 为水平像素,y 为垂直像素,z 无意义)。

【2】Screen.width / Screen.height屏幕的宽度和高度(像素),例如 1920x1080 屏幕中,width=1920height=1080

4.视口坐标系(Viewport Coordinate System)

(1)概念

        视口坐标系是标准化的 2D 坐标系摄像机的左下角为原点(0,0)右上角为(1,1),与屏幕分辨率无关。用于描述物体在摄像机可视范围内的相对位置。

摄像机上的 视口范围

【1】坐标值始终在 [0,1] 范围内(超出则表示在摄像机视野外)。

【2】x=0.5、y=0.5 表示摄像机视野的中心。

5.坐标系转换方法

转换方向核心方法用途说明
世界坐标系 → 物体坐标系InverseTransformPoint / InverseTransformDirection将世界坐标的点 / 方向转换为相对于当前物体的本地坐标(如判断目标在自身的前方还是后方)。
物体坐标系 → 世界坐标系TransformPoint / TransformDirection将本地坐标的点 / 方向转换为世界坐标(如子物体发射子弹时,计算子弹在世界中的初始位置)。
世界坐标系 → 屏幕坐标系Camera.main.WorldToScreenPoint将 3D 世界中的点转换为屏幕上的 2D 像素位置(如显示物体头顶的血条)。
屏幕坐标系 → 世界坐标系Camera.main.ScreenToWorldPoint将屏幕上的点(如鼠标位置)转换为 3D 世界坐标(如点击屏幕生成物体)。
世界坐标系 → 视口坐标系Camera.main.WorldToViewportPoint判断物体在摄像机视野中的相对位置(如检测物体是否移出屏幕)。
视口坐标系 → 世界坐标系Camera.main.ViewportToWorldPoint将视口坐标转换为世界坐标(如在摄像机视野右上角生成特效)。
视口 ↔ 屏幕坐标系ViewportToScreenPoint / ScreenToViewportPoint视口与屏幕坐标的相互转换(如将 UI 位置从像素单位转为标准化单位)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值