Untiy入门学习(一)3D数学(1)之数学计算公共类Mathf
本文简单介绍了Unity中的数学类Mathf及和C#中的Math的区别
目录
(2)Mathf.LerpUnclamped(无限制线性插值)
作用:生成一个 S 形平滑曲线过渡,起始和结束时的速度较慢,中间较快,适合自然缓动效果。
(1) Mathf.Clamp(float value, float min, float max)功能
一、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 |
就这样,再见!
更多推荐
所有评论(0)