Controller
CharacterController 项目里最常见的数值坑
使用 CharacterController 做移动角色时,表面上看最常见的问题是“脚感不对”,但真正容易把项目拖进线上异常的, 通常是数值稳定性。角色重生瞬间的位置、速度投影、地面吸附和重力累积,都会在极端情况下把一个看似正常的流程推成 NaN。
为什么 NaN 很危险
一旦某一帧的速度、位移或目标位置进入 NaN,后续依赖这个值的所有运动计算都会继续失真。更糟的是,很多异常并不会在第一时间中断, 而是先以“偶发瞬移”“特效飞走”“敌人出生位置非法”等形式出现,最后才在控制台里抛出 `Input position is { NaN, NaN, NaN }`。
高风险位置
- 对旧速度向量做投影时,分母使用了极小值甚至零向量
- 重生前一帧角色处于异常物理状态,复用旧速度继续参与新一轮计算
- 基于法线修正水平速度时,没有对向量有效性做保护
- 在空中状态与落地状态之间切换时,重力值和跳跃值被叠加多次
更稳妥的写法
对关键数值做有限值检查,并在发现异常时优先归零,而不是继续把非法值传下去:
static bool IsFinite(float value)
{
return !float.IsNaN(value) && !float.IsInfinity(value);
}
static bool IsFinite(Vector3 value)
{
return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z);
}
if (!IsFinite(velocity))
{
velocity = Vector3.zero;
}
工程建议
我的建议是把“角色是否能动”和“角色数值是否合法”分开检查。前者是玩法问题,后者是稳定性问题。只要把这两个层面拆开,很多难复现的问题都会明显变得可定位。