Unity中10-20FPS低帧率下如何实现物体平滑移动
问题表现
- 目标帧率高于30FPS时,游戏运行状态正常,物体移动效果流畅,满足可玩性要求
- 目标帧率降到10-20FPS区间时,物体移动卡顿严重,无法达到预期游玩要求
已尝试方案及缺陷
- 直接调用Unity原生
Lerp函数:功能可正常运行,但移动效果仍存在明显卡顿,不符合预期 - 引入卡尔曼滤波(Kalman Filter)处理坐标数值:效果有小幅提升,但距离目标平滑效果仍有较大差距
代码中已通过赋值
Application.targetFrameRate参数指定目标帧率,可参考检视面板的相关配置。
当前实现代码
滤波值计算逻辑
float filteredX = kalmanFilterFloat.Update(p.value.x); float filteredY = kalmanFilterFloat.Update(p.value.y); float filteredZ = kalmanFilterFloat.Update(p.value.z);
滤波向量赋值逻辑
Vector3 filteredVec = new Vector3((float)filteredX, (float)filteredY, (float)filteredZ);
滤波Lerp模拟逻辑
private void SimulateFilteredLerp(InterpolatedProperty<Vector3> p, Vector3 filteredVec) { p.prevValue = p.value = Vector3.Lerp(p.value + new Vector3(filteredVec.x, filteredVec.y, filteredVec.z) * masterClock.delta, p.target, masterClock.delta * settings.interpolationSnapping); }
方法调用位置
SimulateFilteredLerp方法在Update生命周期中调用:
SimulateFilteredLerp(p, filteredVec);
低帧率下稳定平滑移动的落地方案
你当前实现卡顿的核心原因是插值逻辑绑定在帧间隔不稳定的Update生命周期:低帧率下Update两次调用的时间间隔最长可达100ms,单帧位移跨度大,无论叠加普通Lerp还是卡尔曼滤波,都无法解决帧间隔不均带来的视觉跳变,按以下步骤调整即可解决问题:
- 拆分逻辑层与渲染层更新周期:将所有物体的位置计算、状态判定逻辑全部迁移到
FixedUpdate中执行,在项目设置中将Fixed Timestep设为固定值(推荐0.02s,对应每秒50次逻辑更新),这部分逻辑的执行间隔完全不随渲染帧率波动,从根源保证位置计算的时间基准稳定。 - 缓存双帧逻辑位置:每次
FixedUpdate执行位置计算时,同步缓存两个值:上一次逻辑更新的位置prevPosition、本次计算得到的最新逻辑位置targetPosition,逻辑层的位置值不直接同步给物体的Transform做渲染。 - 渲染层独立做时间对齐插值:在
Update生命周期中只做渲染位置的插值计算,先算出当前渲染帧距离上一次FixedUpdate的时间偏移占比:float alpha = (Time.time - Time.fixedTime) / Time.fixedDeltaTime;,每帧直接将物体渲染位置设为Vector3.Lerp(prevPosition, targetPosition, alpha),这一步仅修改显示位置,不改动逻辑层的位置数据。 - 移除冗余逻辑:删掉当前代码中叠加的卡尔曼滤波坐标处理、以及写在
Update中的Lerp位移逻辑——这类后置滤波不仅会引入额外的位置延迟,在帧间隔波动的场景下完全无法解决跳变问题;如果是网络同步场景下的远端物体位置抖动,仅需在FixedUpdate的逻辑位置计算层做简单的目标平滑即可,不要在渲染插值层叠加滤波。
补充说明:如果是玩家输入控制的物体,输入采集逻辑可以保留在
Update中,但采集到的输入值需要缓存后传入FixedUpdate做位置计算,禁止直接在Update中修改物体逻辑位置,避免破坏固定时间步长的稳定性。
内容的提问来源于stack exchange,提问作者Mert Balkan
相关产品推荐
相关产品推荐

