解释Step Offset与Slope Limit的物理公式

解读

在国内 Unity 客户端面试里,这道题并不是让你默写“标准物理公式”,而是考察你对 角色控制器(CharacterController) 两大爬坡参数的 底层几何判据与物理意义 是否真正理解。面试官想听到的是:

  1. 这两个值在 引擎内部如何被量化
  2. 它们与 重力、碰撞检测、移动迭代 的耦合关系;
  3. 你能否用 向量数学 把“能上去”或“会滑下来”翻译成可落地的判据,而不是背文档。

知识点

  • Step Offset 的本质是 “单帧垂直台阶允许高度 h”,引擎在 Move 迭代时会把当前运动拆成 水平射线 + 垂直射线 两步:先沿 moveDirection 水平扫一次,若击中障碍,则在击中点正上方 h+ε 处再发一条向上射线,若该射线未击中任何碰撞体,则判定为“可抬升”,随后把角色 position 直接抬升 h。
    物理判据
    h ≤ StepOffset 且 上射线无碰撞 且 水平射线击中点法线 y 分量 < 0.0001(近似垂直面)

  • Slope Limit 的本质是 “可站立面法线与向上向量的夹角 θ”,Unity 在每次 Move 碰撞后,会对 接触点法线 nθ = arccos(n·up) 计算,若 θ > SlopeLimit 则把该接触面标记为“不可站立”,随后 沿斜面切线方向施加滑动速度,其大小由 重力投影 决定:
    slideSpeed = g·sinθ·Δt,方向为 n × (n × up) 归一化。
    因此 SlopeLimit 的物理公式 是:
    θmax = arccos(n·up) ≤ SlopeLimit
    一旦超限,角色进入 “滑动状态”,每帧位移附加 Δx = ½·g·sinθ·Δt²

  • 两者共同决定 “能否站稳”
    若角色同时满足
    (1) 所有接触面 θ ≤ SlopeLimit
    (2) 下一帧预计抬升高度 ≤ StepOffset
    isGrounded 返回 true,否则为 false。

答案

Step Offset 没有显式“F=ma”式公式,其 几何判据 为:
Δy = max{0, hit.point.y - footPos.y} ≤ StepOffset
引擎在 水平射线检测 后,若 Δy 在允许范围内且上方无遮挡,则把 position.y += Δy,完成抬升。

Slope Limit 的 物理公式 为:
θ = arccos(n·up)
θ > SlopeLimit 时,角色进入滑动,每帧附加位移:
Δslide = g·sinθ·Δt·tangentDir
其中 tangentDir = normalize(n × (n × up)),g 为 Physics.gravity.magnitude

拓展思考

  1. 热更新场景下的兼容性:在 HybridCLRILRuntime 热更层,如果你自己实现了一套“胶囊爬坡”逻辑,必须 手动复现 上述两条判据,否则会出现 “热更端能上去,原生端滑下来” 的诡异 Bug。
  2. 性能陷阱:Step Offset 每帧会额外触发 2~3 条射线,在 地形网格(TerrainCollider) 上若未开启 “Enable Adaptive Force”,会造成 GC.Alloc 抖动;建议对 静态场景 预烘焙 “台阶高度场”,用 二维数组 代替实时射线。
  3. XR 适配:在 Quest 3 透视 AR 模式,真实地面法线由 空间锚点 提供,可能随时变化;此时需要 动态缩放 SlopeLimit
    θallow = baseSlopeLimit · (1 - 0.3·headAcceleration)
    防止用户快速摇头时因瞬时法线抖动导致 “伪滑动”