Untiy入门学习(一)3D数学(1)之数学计算公共类Mathf
目录
一、Unity Mathf 类的主要方法和属性
1、常用静态属性
2、重要静态方法
基础数学工具方法
取整与舍入方法
极值与数值逼近
周期与噪声生成
柏林噪声 vs 随机数
插值与平滑:
(1)Mathf.Lerp(线性插值)
(2)Mathf.LerpUnclamped(无限制线性插值)
(3)Mathf.SmoothStep(平滑过渡)
作用:生成一个 S 形平滑曲线过渡,起始和结束时的速度较慢,中间较快,适合自然缓动效果。
示例:平滑开门动画
(4)Mathf.SmoothDamp(阻尼平滑过渡)
总结与对比
数值限制与映射
(1) Mathf.Clamp(float value, float min, float max)功能
示例:限制玩家血量
示例:UI 渐入渐出效果
示例:循环移动平台,一直往指定方向移动直到到达后返回起点
示例:动态进度条
扩展用法:反向映射非连续区间
对比总结
三角函数与角度处理
其他实用方法
二、Mathf 与 C# Math 类的区别
三、总结
Unity Mathf 类完整总结
1、常用静态属性
2、基础数学工具方法
3、取整与舍入方法
4、极值与数值逼近
5、周期与噪声生成
6、插值与平滑
7、数值限制与映射
8、其他实用方法
9、Mathf 与 C# Math 的对比
10、三角函数与角度处理
一、Unity Mathf 类的主要方法和属性
1、常用静态属性
Mathf.Deg2Rad 和 Mathf.Rad2Deg
用于角度与弧度的转换。Deg2Rad = π/180,Rad2Deg = 180/π。
示例:将角度转为弧度 float radians = 90 * Mathf.Deg2Rad;
Mathf.Epsilon
一个极小的浮点数值(约 1e-45),用于避免浮点数精度误差的比较操作。
Mathf.Infinity 和 Mathf.NegativeInfinity
表示正负无穷大的常量,常用于范围判断(如射线检测的无限制距离)。
Mathf.PI
表示圆周率 π 的浮点数值(精度为 float)。
2、重要静态方法
基础数学工具方法
(1)Mathf.Abs(float value)
功能:返回绝对值(忽略正负号)。
(2)Mathf.Sign(float value)
功能:返回数值的符号(1 表示正数,-1 表示负数,0 表示零)。
(3)Mathf.Sqrt(float value)
功能:计算平方根。
注意:若 value < 0,返回 NaN(非数字)。
取整与舍入方法
(1)Mathf.Ceil(float value)
功能:向上取整(返回大于等于 value 的最小整数,类型为 float)。
float ceilResult = Mathf.Ceil(3.2f); // 返回 4.0f
(2) Mathf.Floor(float value)
功能:向下取整(返回小于等于 value 的最大整数,类型为 float)。
float floorResult = Mathf.Floor(3.8f); // 返回 3.0f
(3)Mathf.Round(float value)
功能:四舍五入(使用“银行家舍入法”:当 value 恰好在两个整数中间时,舍入到最近的偶数)
float round1 = Mathf.Round(2.5f); // 返回 2.0f(中间值舍入到偶数)
float round2 = Mathf.Round(3.5f); // 返回 4.0f
(4)Mathf.CeilToInt (向上取整)与 Mathf.FloorToInt(向下取整)
功能:直接返回 int 类型的取整结果。
int ceilInt = Mathf.CeilToInt(3.2f); // 返回 4
int floorInt = Mathf.FloorToInt(3.8f); // 返回 3
极值与数值逼近
(1)Mathf.Max 和 Mathf.Min
功能:返回多个数值中的最大或最小值。
重载:支持 float、int 及参数列表(如 Mathf.Max(1, 2, 3))。
示例:
float maxDamage = Mathf.Max(baseDamage, criticalDamage); // 取伤害最大值
float minSpeed = Mathf.Min(currentSpeed, maxSpeedLimit); // 限制最低速度
(2)Mathf.MoveTowards(float current, float target, float maxDelta)
功能:以固定步长 maxDelta 从 current 向 target 移动,避免超出目标值。
与 Lerp 的区别:Lerp 按比例插值,MoveTowards 按固定速度逼近。
public float speed = 5.0f;
void Update() {transform.position = Vector3.MoveTowards(transform.position,target.position,speed * Time.deltaTime);
}
周期与噪声生成
(1)Mathf.PingPong(float t, float length)
功能:在 [0, length] 区间内往返循环数值(类似乒乓球运动)。
公式:PingPong(t, length) = length - Mathf.Abs(Repeat(t, 2 * length) - length)
示例(物体往返移动):
void Update() {float x = Mathf.PingPong(Time.time * 2, 10); // 在 0~10 之间往返transform.position = new Vector3(x, 0, 0);
}
(2)Mathf.PerlinNoise(float x, float y)
是 Unity 中用于生成柏林噪声(Perlin Noise)的核心方法。柏林噪声是一种自然、连续的随机噪声算法,广泛用于程序化生成地形、纹理、云层、火焰等自然效果。与普通随机数不同,柏林噪声具有以下特点:
柏林噪声的核心特性
连续性:噪声值在相邻点之间平滑过渡,没有突变。
自然性:生成的图案类似自然界中的地形或云层。
可重复性:相同输入坐标 (x, y) 永远返回相同的噪声值。
功能:生成柏林噪声值(范围 [0,1]),用于自然随机效果(地形、纹理等)。
参数:输入坐标 x 和 y,建议使用连续的小幅增量(如 0.1f)。
示例(生成地形高度):
public int width = 100;
public int height = 100;
public float scale = 20f;void GenerateTerrain() {for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {float xCoord = (float)x / width * scale;float yCoord = (float)y / height * scale;float heightValue = Mathf.PerlinNoise(xCoord, yCoord);// 根据 heightValue 设置地形高度}}
}
柏林噪声 vs 随机数
特性 | 柏林噪声 | 随机数 (Random.Range ) |
---|---|---|
连续性 | 相邻值平滑过渡 | 完全随机,无连续性 |
自然性 | 适合模拟自然现象(地形、云层) | 适合离散事件(暴击率、掉落) |
性能 | 计算成本较高 | 计算成本极低 |
插值与平滑:
(1)Mathf.Lerp
(线性插值)
作用:在 a 和 b 之间按比例 t 进行线性插值。当 t ∈ [0,1] 时,结果在 [a, b] 范围内;t=0 返回 a,t=1 返回 b。
基本原理:Lerp(a, b, t) = a + (b - a) * t
例如该函数实现一个物体的颜色渐变:
public class ColorLerp : MonoBehaviour
{public Color startColor = Color.red;public Color endColor = Color.blue;public float duration = 3.0f;private float t = 0;void Update(){t += Time.deltaTime / duration;// 使用 Lerp 插值颜色GetComponent<Renderer>().material.color = Color.Lerp(startColor, endColor, t);}
}
注意:Lerp 的 t 通常需要随时间递增,但直接使用 Time.deltaTime 可能导致动画不完成(需确保 t 最终达到 1)。
(2)Mathf.LerpUnclamped
(无限制线性插值)
作用:允许 t 超出 [0,1],实现外插值。当 t < 0 或 t > 1 时,结果会超出 a 和 b 的范围。
示例:超出范围的移动
public class MoveBeyond : MonoBehaviour
{public Transform startPoint;public Transform endPoint;public float speed = 0.5f;private float t = 0;void Update(){t += Time.deltaTime * speed;// t 可能超过 1,物体会移动到终点之后transform.position = Vector3.LerpUnclamped(startPoint.position, endPoint.position, t);}
}
(3)Mathf.SmoothStep
(平滑过渡)
作用:生成一个 S 形平滑曲线过渡,起始和结束时的速度较慢,中间较快,适合自然缓动效果。
SmoothStep(a, b, t) = a + (b - a) * (t² * (3 - 2t))
示例:平滑开门动画
public class DoorController : MonoBehaviour
{public float openAngle = 90f;public float smoothTime = 2.0f;private float currentAngle = 0;private float t = 0;void Update(){t += Time.deltaTime / smoothTime;// 使用 SmoothStep 实现平滑旋转currentAngle = Mathf.SmoothStep(0, openAngle, t);transform.rotation = Quaternion.Euler(0, currentAngle, 0);}
}
(4)Mathf.SmoothDamp
(阻尼平滑过渡)
作用:模拟阻尼运动,逐渐逼近目标值,适合相机跟随、物体缓动停止等场景。它会自动计算平滑速度,避免突然停止。
参数
current:当前值
target:目标值
currentVelocity:当前速度(需声明为引用参数 ref)
smoothTime:过渡时间(秒)
maxSpeed(可选):最大限制速度
例如:相机平滑跟随玩家
public class CameraFollow : MonoBehaviour
{public Transform target;public float smoothTime = 0.3f;private Vector3 velocity = Vector3.zero;void LateUpdate(){Vector3 targetPosition = target.position + new Vector3(0, 5, -10);// 使用 SmoothDamp 实现平滑跟随transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);}
}
velocity 需声明为类成员变量以保持连续性。
smoothTime 越小,跟随速度越快。
maxSpeed 可防止高速移动时抖动。
总结与对比
方法 | 特点 | 适用场景 |
---|---|---|
Lerp | 线性匀速过渡 | 颜色渐变、简单位置移动 |
LerpUnclamped | 允许超出起点和终点 | 弹道轨迹、快速掠过动画 |
SmoothStep | S 形曲线,缓入缓出 | 平滑的 UI 动画、旋转效果 |
SmoothDamp | 阻尼运动,自动计算速度,避免抖动 | 相机跟随、物体缓动停止 |
注意:上面举的示例只是因为,有明显效果,才使用的其他类里面的相关插值函数。实际上,这些插值函数都是依赖于Mathf的。
数值限制与映射
在 Unity 的 Mathf
类中,Clamp
、Clamp01
、Repeat
和 InverseLerp
是用于数值限制、循环和区间映射的核心工具。
(1) Mathf.Clamp(float value, float min, float max)
功能
将 value 限制在 [min, max] 区间内。
如果 value < min,返回 min。
如果 value > max,返回 max。
如果 min > max,Unity 会自动交换 min 和 max,确保逻辑正确。
参数
value:需要限制的原始值。
min:区间下限。
max:区间上限。
示例:限制玩家血量
public class PlayerHealth : MonoBehaviour
{public float currentHealth = 50f;public float maxHealth = 100f;public float minHealth = 0f;void TakeDamage(float damage){currentHealth -= damage;currentHealth = Mathf.Clamp(currentHealth, minHealth, maxHealth);Debug.Log("当前血量:" + currentHealth);}void Heal(float amount){currentHealth += amount;currentHealth = Mathf.Clamp(currentHealth, minHealth, maxHealth);Debug.Log("当前血量:" + currentHealth);}
}
(2)Mathf.Clamp01(float value)
功能
将 value 限制在 [0, 1] 区间。等价于 Clamp(value, 0, 1)。
使用场景
颜色透明度(Alpha)、进度比例、归一化参数。
示例:UI 渐入渐出效果
public class UIFade : MonoBehaviour
{public CanvasGroup uiGroup;public float fadeSpeed = 0.5f;private float targetAlpha = 0f;void Update(){// 按下空格键切换显隐if (Input.GetKeyDown(KeyCode.Space))targetAlpha = (targetAlpha == 0) ? 1 : 0;// 平滑过渡透明度uiGroup.alpha = Mathf.Lerp(uiGroup.alpha, targetAlpha, Time.deltaTime * fadeSpeed);// 确保透明度在 [0,1] 范围内uiGroup.alpha = Mathf.Clamp01(uiGroup.alpha);}
}
(3)Mathf.Repeat(float t, float length)
功能
将数值 t 循环限制在 [0, length) 区间(左闭右开)。
当 t 超过 length 时,会从 0 重新开始。
支持负数:Repeat(-1, 5) 返回 4。
Repeat(t, length) = t - length * floor(t / length)
示例:循环移动平台,一直往指定方向移动直到到达后返回起点
public class MovingPlatform : MonoBehaviour
{public float speed = 1f;public float moveDistance = 5f;private Vector3 startPos;void Start(){startPos = transform.position;}void Update(){// 计算循环时间(周期为 moveDistance/speed 秒)float t = Time.time * speed;float x = Mathf.Repeat(t, moveDistance);// 平台在 startPos.x 到 startPos.x + moveDistance 之间来回移动transform.position = startPos + new Vector3(x, 0, 0);}
}
(4)Mathf.InverseLerp(float a, float b, float value)
功能
计算 value 在 [a, b] 区间中的归一化比例位置。
如果 value <= a,返回 0。
如果 value >= b,返回 1。
如果 a = b,返回 0(避免除以零错误)。
InverseLerp(a, b, value) = (value - a) / (b - a)
示例:动态进度条
public class ProgressBar : MonoBehaviour
{public Transform loadingBar;public float minValue = 0f;public float maxValue = 100f;public float currentValue = 30f;void Update(){// 计算进度比例(0~1)float progress = Mathf.InverseLerp(minValue, maxValue, currentValue);// 应用进度到UI(假设进度条Scale从0到1)loadingBar.localScale = new Vector3(progress, 1, 1);}
}
扩展用法:反向映射非连续区间
// 将 [-10, 10] 映射到 [0, 1]
float t = Mathf.InverseLerp(-10, 10, temperature);
// 如果 temperature = 5,则 t = 0.75
对比总结
方法 | 核心功能 | 典型场景 | 返回值范围 |
---|---|---|---|
Clamp | 硬性限制数值范围 | 血量、冷却时间 | [min, max] |
Clamp01 | 限制数值到 0~1 | 透明度、归一化参数 | [0, 1] |
Repeat | 循环数值 | 周期性动画、计时器 | [0, length) |
InverseLerp | 计算数值在区间中的比例位置 | 进度条、动态插值参数 | [0, 1] (可超出) |
三角函数与角度处理
Sin、Cos、Tan这些我们后面会专门单独学习这个
接受弧度参数,与 Math 类一致。
DeltaAngle(float current, float target)
计算两个角度间的最小差值(考虑360°循环)。
其他实用方法
(1)Mathf.Approximately(float a, float b)
功能:判断两个浮点数是否近似相等(避免精度误差)。
if (Mathf.Approximately(playerHealth, 0)) {// 玩家生命值接近0时触发死亡
}
(2)Mathf.NextPowerOfTwo(int value)
功能:返回大于等于 value 的最小 2 的幂次数(如 7 → 8,9 → 16)。
(3)Mathf.ClosestPowerOfTwo(int value)
功能:返回最接近 value 的 2 的幂次数(如 7 → 8,15 → 16)。
(4)Mathf.Pow(float powerBase, float exponent)
作用:计算一个数的 n 次幂(即 powerBase^exponent)。
参数:
powerBase:底数(基数)。
exponent:指数(幂)。
返回值类型:float。
// 计算 2 的 3 次方(2^3 = 8)
float result = Mathf.Pow(2, 3); // 返回 8.0f
print(result); // 输出 8
注意:
如果 exponent 为负数,结果为 1 / (base^|exponent|)(例如 Pow(2, -3) → 0.125f)。
当 powerBase 为负数且 exponent 为非整数时,返回 NaN(如 Pow(-2, 0.5f))。
(5)Mathf.IsPowerOfTwo(int value)
作用:判断一个整数是否是 2 的幂次方(如 1, 2, 4, 8, 16...)。
参数:value:需要判断的整数。
返回值类型:bool。
bool isPowerOfTwo1 = Mathf.IsPowerOfTwo(4); // true(4 = 2^2)
bool isPowerOfTwo2 = Mathf.IsPowerOfTwo(3); // false
bool isPowerOfTwo3 = Mathf.IsPowerOfTwo(0); // false(0 不是 2 的幂次)
print(isPowerOfTwo1); // 输出 True
二、Mathf 与 C# Math 类的区别
1. 数据类型与精度
Mathf 针对 float 类型优化,适合Unity引擎中大量使用的单精度浮点数运算。
Math 类(位于 System 命名空间)默认使用 double 类型,精度更高但性能开销略大。
2. 功能扩展 游戏开发专用方法
Mathf 提供了 Lerp、SmoothDamp、DeltaAngle 等方法,专为游戏动画、物理模拟设计,而 Math 类缺少这些功能。
角度转换常量
Mathf.Deg2Rad 和 Mathf.Rad2Deg 简化了角度与弧度的转换,而使用 Math 类需手动计算(如 Math.PI / 180)。
3. 方法实现差异
Clamp 方法的存在性
在较新的C#版本中,Math 类可能支持 Clamp,但Unity的传统Mono版本可能依赖 Mathf 的实现。
Math.PI vs Mathf.PI
Math.PI 是 double 类型(更高精度),而 Mathf.PI 是 float 类型。
小结:Mathf 类 是Unity游戏开发的首选工具,提供高效且针对性的数学方法,适合处理浮点数运算、动画插值、角度转换等常见需求。
C# Math 类 更适用于通用编程和高精度计算,但在Unity中可能因类型转换和功能缺失不如 Mathf 便捷。
三、总结
Unity Mathf 类完整总结
1、常用静态属性
属性名 | 作用 | 值/公式 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Deg2Rad | 角度转弧度系数 | π/180 | float | 90 * Deg2Rad → 1.5708f (π/2) |
Mathf.Rad2Deg | 弧度转角度系数 | 180/π | float | Mathf.PI * Rad2Deg → 180 |
Mathf.Epsilon | 极小的浮点数值(避免精度误差) | ≈1e-45 | float | if (a - b < Epsilon) |
Mathf.Infinity | 正无穷大 | float.PositiveInfinity | float | Physics.Raycast(..., Infinity) |
Mathf.NegativeInfinity | 负无穷大 | float.NegativeInfinity | float | Mathf.Min(-Infinity, 0) → -Infinity |
Mathf.PI | 圆周率 π(单精度) | 3.14159274f | float | Mathf.Sin(Mathf.PI / 2) → 1 |
2、基础数学工具方法
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Abs | 绝对值 | value: float | float | Abs(-5.5f) → 5.5f |
Mathf.Sign | 数值符号(1/-1/0) | value: float | float | Sign(-3.2f) → -1 |
Mathf.Sqrt | 平方根 | value: float | float | Sqrt(16) → 4 |
3、取整与舍入方法
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Ceil | 向上取整 | value: float | float | Ceil(3.2f) → 4.0f |
Mathf.Floor | 向下取整 | value: float | float | Floor(3.8f) → 3.0f |
Mathf.Round | 四舍五入(银行家舍入法) | value: float | float | Round(2.5f) → 2.0f |
Mathf.CeilToInt | 向上取整为整数 | value: float | int | CeilToInt(3.2f) → 4 |
Mathf.FloorToInt | 向下取整为整数 | value: float | int | FloorToInt(3.8f) → 3 |
4、极值与数值逼近
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Max | 取最大值 | params float[] | float | Max(1, 5, 3) → 5 |
Mathf.Min | 取最小值 | params float[] | float | Min(1, 5, 3) → 1 |
Mathf.MoveTowards | 固定步长逼近目标值 | current, target, maxDelta | float | MoveTowards(2, 10, 3) → 5 |
5、周期与噪声生成
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.PingPong | 往返循环数值(0→length→0) | t: float, length: float | float | PingPong(Time.time, 5) |
Mathf.PerlinNoise | 生成柏林噪声值(自然随机) | x: float, y: float | float | PerlinNoise(xCoord, yCoord) |
6、插值与平滑
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Lerp | 线性插值 | a, b, t | float | Lerp(0, 10, 0.5f) → 5 |
Mathf.LerpUnclamped | 无限制线性插值 | a, b, t | float | LerpUnclamped(0, 10, 1.5f) → 15 |
Mathf.SmoothStep | S 形曲线平滑过渡 | a, b, t | float | SmoothStep(0, 1, 0.5f) → 0.5 |
Mathf.SmoothDamp | 阻尼平滑过渡 | current, target, ref velocity, smoothTime | float | SmoothDamp(pos, targetPos, ref vel, 0.3f) |
7、数值限制与映射
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Clamp | 限制数值在区间内 | value, min, max | float | Clamp(10, 0, 5) → 5 |
Mathf.Clamp01 | 限制数值在 [0,1] | value: float | float | Clamp01(-0.5f) → 0 |
Mathf.Repeat | 循环数值在 [0, length) | t: float, length: float | float | Repeat(12, 5) → 2 |
Mathf.InverseLerp | 计算数值在区间中的比例位置 | a, b, value | float | InverseLerp(0, 10, 5) → 0.5 |
8、其他实用方法
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Approximately | 判断浮点数近似相等 | a: float, b: float | bool | Approximately(0.1f, 0.1000001f) → true |
Mathf.ClosestPowerOfTwo | 返回最接近的 2 的幂次 | value: int | int | ClosestPowerOfTwo(7) → 8 |
Mathf.NextPowerOfTwo | 返回大于等于值的 2 的幂次 | value: int | int | NextPowerOfTwo(7) → 8 |
Mathf.Pow | 计算幂次方 | base, exponent | float | Pow(2, 3) → 8.0f |
Mathf.IsPowerOfTwo | 判断是否为 2 的幂次 | value: int | bool | IsPowerOfTwo(8) → true |
9、Mathf 与 C# Math 的对比
对比维度 | Unity Mathf | C# Math |
---|---|---|
数据类型 | 针对 float 优化,适合实时游戏计算 | 默认使用 double ,精度更高但性能开销较大 |
功能扩展 | 提供游戏开发专用方法(Lerp、SmoothDamp 等) | 仅提供基础数学运算(Sin、Log 等) |
角度转换 | 内置 Deg2Rad 和 Rad2Deg 常量 | 需手动计算(如 Math.PI / 180 ) |
性能优化 | 针对 Unity 引擎底层优化,适合高频调用 | 无特殊优化,适合通用计算 |
典型场景 | 游戏逻辑、动画、物理模拟 | 科学计算、通用编程 |
10、三角函数与角度处理
方法名 | 作用 | 参数 | 返回值类型 | 示例 |
---|---|---|---|---|
Mathf.Sin | 计算正弦值(弧度) | radians: float | float | Sin(Mathf.PI/2) → 1 |
Mathf.DeltaAngle | 计算两角度的最小差值 | current, target | float | DeltaAngle(350, 10) → 20 |
就这样,再见!