Unity 的 Mathf 类中,用于 数值平滑(渐变、缓冲、缓动) 的核心方法有 5 个,覆盖不同平滑场景(线性渐变、带减速缓冲、缓入缓出、往返平滑等),以下是完整整理,含 方法功能、适用场景、可运行示例,方便直接套用:

一、核心数值平滑方法(按常用度排序)

1. Mathf.SmoothDamp(平滑阻尼,最常用)

功能

自然减速效果 的平滑趋近目标值,通过速度变量(引用类型)模拟惯性,最终平稳停在目标值,不会超调。

关键特性

  • 有“缓冲感”,适合需要自然减速的场景(如相机跟随、数值缓冲);
  • 需持续在 Update 中调用,速度变量需提前初始化且作为 ref 参数传入。

示例代码(相机平滑跟随目标X轴)

public Transform target; // 跟随目标
private float currentX;
private float velocity = 0f; // 速度变量(必须初始化)
public float smoothTime = 0.3f; // 平滑时间(越小越快)

void Start()
{
    currentX = transform.position.x;
}

void Update()
{
    // 平滑阻尼趋近目标X坐标
    currentX = Mathf.SmoothDamp(currentX, target.position.x, ref velocity, smoothTime);
    // 应用到相机位置
    transform.position = new Vector3(currentX, transform.position.y, transform.position.z);
}

适用场景

相机跟随、UI元素平滑移动、血条/音量等数值缓冲、物体惯性运动。

2. Mathf.SmoothStep(缓入缓出平滑)

功能

fromto 之间做 S形曲线过渡(缓入+缓出),t 在 0~1 范围内时,数值先慢后快再慢,比线性插值更自然。

关键特性

  • 无需持续调用,只要 t 从 0 渐变到 1 即可触发平滑效果;
  • t 超出 0~1 时,结果会紧贴 fromto(不会外推)。

示例代码(UI按钮缩放动画)

public Transform btnTransform;
public float duration = 1f; // 动画时长

void Update()
{
    // t 从 0 循环到 1(配合PingPong实现往返)
    float t = Mathf.PingPong(Time.time / duration, 1f);
    // 缓入缓出缩放(0.8→1.2→0.8)
    float scale = Mathf.SmoothStep(0.8f, 1.2f, t);
    btnTransform.localScale = Vector3.one * scale;
}

适用场景

UI动画(缩放、位移、透明度)、物体缓动效果、平滑过渡的参数调整。

3. Mathf.Lerp(线性插值,基础平滑)

功能

ab 之间做 线性渐变(匀速过渡),t 为 0 时返回 at 为 1 时返回 b,中间值匀速变化。

关键特性

  • 平滑效果均匀,但无减速,适合需要匀速渐变的场景;
  • 需持续在 Update 中调用,通过 t = speed * Time.deltaTime 控制渐变速度(帧率无关)。

示例代码(音量平滑调节)

public AudioSource audioSource;
public float targetVolume = 0.7f;
public float smoothSpeed = 1f;

void Update()
{
    // 线性插值平滑调节音量
    float currentVolume = Mathf.Lerp(audioSource.volume, targetVolume, smoothSpeed * Time.deltaTime);
    audioSource.volume = currentVolume;
    
    // 接近目标时停止打印(避免无限循环)
    if (Mathf.Approximately(currentVolume, targetVolume))
    {
        Debug.Log("音量调节完成");
        enabled = false;
    }
}

适用场景

匀速数值过渡、简单移动渐变、参数线性调整(如亮度、透明度)。

4. Mathf.MoveTowards(匀速趋近,无超调)

功能

匀速逼近目标值,每次移动的最大步长为 maxDelta,到达目标后直接停止(不会超调),本质是“限制步长的线性渐变”。

关键特性

  • Lerp 更精准控制移动速度,适合需要明确“每秒移动X单位”的场景;
  • 无需手动处理目标边界,到达后自动停住。

示例代码(物体匀速平滑移动到目标点)

public Transform target;
public float moveSpeed = 3f; // 每秒移动3个单位
private Vector3 currentPos;

void Start()
{
    currentPos = transform.position;
}

void Update()
{
    // 匀速趋近目标X坐标(Y、Z保持不变)
    currentPos.x = Mathf.MoveTowards(currentPos.x, target.position.x, moveSpeed * Time.deltaTime);
    transform.position = currentPos;
    
    // 到达目标时提示
    if (Mathf.Approximately(currentPos.x, target.position.x))
    {
        Debug.Log("移动完成");
        enabled = false;
    }
}

适用场景

角色匀速移动、物体追击、数值匀速变化(如倒计时、进度条填充)。

5. Mathf.PingPong + 平滑方法(往返平滑)

功能

PingPong 本身是“往返循环”方法(0→length→0),配合 Lerp/SmoothStep 可实现 往返平滑过渡(如呼吸灯、摇摆动画)。

关键特性

  • 无需手动控制“往返方向”,PingPong 自动循环 t 值;
  • 结合 SmoothStep 可实现往返缓入缓出,效果更自然。

示例代码(呼吸灯效果)

public Light pointLight;
public float duration = 2f; // 一个往返周期(亮→暗→亮)

void Update()
{
    // t 从 0 循环到 1(PingPong 控制往返)
    float t = Mathf.PingPong(Time.time / duration, 1f);
    // 结合 SmoothStep 实现缓入缓出的亮度变化(0.5→2→0.5)
    float intensity = Mathf.SmoothStep(0.5f, 2f, t);
    pointLight.intensity = intensity;
}

适用场景

呼吸灯、物体往返摇摆、UI元素闪烁、数值周期性平滑波动。

二、角度专用平滑方法(数值平滑的衍生场景)

如果需要平滑处理 角度旋转(如角色转向、相机旋转),Mathf 提供了 3 个角度专用平滑方法,自动处理 360° 边界问题(避免绕远路):

1. Mathf.SmoothDampAngle(角度平滑阻尼)

public float targetAngle = 90f;
private float currentAngle = 0f;
private float velocity = 0f;
public float smoothTime = 0.2f;

void Update()
{
    // 平滑阻尼旋转(自动走最短路径)
    currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref velocity, smoothTime);
    transform.rotation = Quaternion.Euler(0, currentAngle, 0);
}

2. Mathf.LerpAngle(角度线性插值)

public float targetAngle = 180f;
private float currentAngle = 0f;

void Update()
{
    // 角度线性平滑(自动处理360°边界)
    currentAngle = Mathf.LerpAngle(currentAngle, targetAngle, 0.5f * Time.deltaTime);
    transform.rotation = Quaternion.Euler(0, currentAngle, 0);
}

3. Mathf.MoveTowardsAngle(角度匀速趋近)

public float targetAngle = 270f;
private float currentAngle = 0f;
public float rotateSpeed = 60f; // 每秒转60度

void Update()
{
    // 角度匀速旋转(自动走最短路径)
    currentAngle = Mathf.MoveTowardsAngle(currentAngle, targetAngle, rotateSpeed * Time.deltaTime);
    transform.rotation = Quaternion.Euler(0, currentAngle, 0);
}

三、平滑方法选择指南(避免踩坑)

需求场景 推荐方法 核心优势
带减速的自然平滑(如相机跟随) Mathf.SmoothDamp 有惯性,效果自然,无超调
缓入缓出的动画(如UI缩放) Mathf.SmoothStep S形曲线,比Lerp更柔和
匀速渐变(如音量调节) Mathf.Lerp 简单直接,适合基础平滑需求
精准控制速度(如角色移动) Mathf.MoveTowards 明确步长,到达目标自动停止
往返平滑(如呼吸灯) Mathf.PingPong + SmoothStep 自动循环,无需手动控制方向
角度旋转(如角色转向) SmoothDampAngle/LerpAngle 自动处理360°边界,避免绕远路

四、关键使用注意事项

  1. 持续调用要求SmoothDamp/Lerp/MoveTowards 需在 Update/FixedUpdate 中持续调用,单次调用仅返回当前插值结果;
  2. 速度变量初始化SmoothDamp/SmoothDampAnglevelocity 参数必须初始化(如 float velocity = 0f),且是 ref 类型(不能直接传字面量);
  3. 帧率无关:所有平滑方法的“速度/步长”需乘以 Time.deltaTime,确保不同帧率下平滑效果一致;
  4. 边界处理:角度平滑优先用专用方法(如 LerpAngle),避免手动计算角度差导致的绕路问题;
  5. 停止条件:用 Mathf.Approximately 判断是否到达目标值(避免浮点数精度误差),防止无限循环。

这些方法覆盖了 Unity 开发中 95% 以上的数值平滑场景,结合使用可实现自然、流畅的动画和数值过渡效果。