You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity移动端移动卡顿但编辑器正常的协程移动问题

解决Unity移动端方块移动不流畅的问题

核心问题分析

你的代码在编辑器流畅但移动端卡顿,核心原因集中在这几点:

  • 协程yield时机选择不当,导致移动逻辑与渲染/主更新循环不同步,产生视觉延迟
  • 成员变量startPos/targetPos存在被外部逻辑意外修改的风险,加上移动端帧率波动时的时间累加误差,破坏了插值平滑度
  • WaitForEndOfFrame会让移动逻辑在所有渲染操作后执行,位置更新滞后于视觉帧,放大卡顿感

优化方案

1. 改用yield return null替代WaitForEndOfFrame

yield return null会让协程在下一个Update周期执行,与游戏主逻辑完全同步,避免渲染后延迟更新位置带来的脱节感。

2. 将位置变量改为局部变量

把startPos和targetPos改为循环内的局部变量,彻底杜绝外部逻辑篡改插值基准的可能。

3. 使用Time.unscaledDeltaTime累加时间

防止游戏时间缩放(如暂停、慢动作)影响移动节奏,同时适配移动端的时间计算精度。

4. 限制插值参数最大值

用Mathf.Clamp01确保插值参数不超过1,避免因时间累加误差导致位置超调,保证最后一帧平滑过渡到目标点。

修改后的代码

private IEnumerator Move(int steps)
{
    var shape = particleSystem.shape;

    for(int i = 0; i < steps; i++)
    {
        if (!canMove(dir)) continue;

        isMoving = true;
        shape.rotation = new Vector3(0f, yParts(), 0f);
        particleSystem.Play();
        
        // 改用局部变量,避免外部逻辑干扰
        float elapsedTime = 0f;
        Vector3 startPos = transform.position;
        Vector3 targetPos = startPos + dir;

        while(elapsedTime < timeToMove)
        {
            // 限制插值范围,防止超调
            float t = Mathf.Clamp01(elapsedTime / timeToMove);
            transform.position = Vector2.Lerp(startPos, targetPos, t);
            // 用unscaledDeltaTime保证时间累加不受游戏时间缩放影响
            elapsedTime += Time.unscaledDeltaTime;
            // 回到主Update循环,同步逻辑与渲染
            yield return null;
        }
        // 确保最终位置绝对准确
        transform.position = targetPos;
        isMoving = false;
    }
}

额外优化建议

  • 开启Unity的Dynamic Batching或GPU Instancing,减少移动端Draw Call开销,间接提升移动流畅度
  • 检查canMove(dir)方法是否包含耗时操作,移动端CPU性能有限,避免在循环内执行复杂碰撞检测
  • 测试时可关闭移动端的VSync,部分设备的VSync会强制帧率对齐屏幕刷新率,导致移动动画看起来卡顿(粒子不受影响是因为粒子系统采用独立更新逻辑)

内容的提问来源于stack exchange,提问作者3a4em

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:24:31