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

Unity C# 如何实现无冻结等待 延迟重载游戏场景

障碍物触发后非阻塞延迟重载关卡实现

原有代码的问题根源

  • System.Threading.Thread.Sleep 是强制阻塞主线程的同步方法,Unity 的物理模拟、玩家移动、相机渲染、输入响应全部运行在主线程上,调用该方法会直接暂停主线程的所有任务执行,导致整个游戏进程冻结,完全无法实现“保留玩家一小段时间移动状态”的效果。
  • 原代码在碰撞触发的第一时间就关闭了移动组件、相机组件,和“碰撞后先保留一段时间移动状态再重载”的需求逻辑错位,即使去掉Sleep调用,也会立刻停止玩家移动,达不到预期效果。

推荐实现方案

使用Unity原生的协程(Coroutine)实现非阻塞延迟等待。协程是Unity专门为分帧延迟执行设计的机制,等待过程中不会打断主线程的游戏逻辑运行,可以完整保留等待时段内的玩家移动、物理模拟效果,等到延迟时间结束后再执行重载逻辑。

实现步骤如下:

  1. 确保脚本引入所需命名空间:
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
  2. 将原有碰撞回调中的阻塞逻辑替换为协程启动逻辑,调整组件关闭的时机到延迟结束之后:
    void OnCollisionEnter(Collision inf)
    {
        if (inf.collider.CompareTag("Obstacle"))
        {
            // 启动协程,不阻塞主线程
            StartCoroutine(DelayReloadLevel());
        }
    }
    
    IEnumerator DelayReloadLevel()
    {
        // 等待1秒,等待过程中所有游戏逻辑正常运行
        yield return new WaitForSeconds(1f);
        
        // 延迟结束后再执行原有的组件关闭、重载逻辑
        movement.enabled = false;
        Camera.enabled = false;
        SceneManager.LoadScene("Level");
    }
    

其他可选实现

如果不需要复杂的等待逻辑,也可以用MonoBehaviour自带的Invoke方法实现更轻量化的延迟调用,代码写法更简洁:

void OnCollisionEnter(Collision inf)
{
    if (inf.collider.CompareTag("Obstacle"))
    {
        // 1秒后执行LoadLevel方法
        Invoke(nameof(LoadLevel), 1f);
    }
}

void LoadLevel()
{
    movement.enabled = false;
    Camera.enabled = false;
    SceneManager.LoadScene("Level");
}

注意事项

  • 协程默认使用游戏时间计算等待时长,如果游戏存在时间缩放(比如慢动作、暂停逻辑),需要不受缩放影响的等待效果,可以将等待语句替换为 yield return new WaitForSecondsRealtime(1f)。
  • 代码中判断标签推荐使用CompareTag方法,相比直接字符串对比的tag属性写法,性能更好,还能避免拼写错误导致的运行时报错。
  • 禁止在主线程使用各类线程阻塞方法(比如Thread.Sleep),这类方法会直接打断Unity的游戏循环,造成游戏假死。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 15:54:04