海南省住房和建设厅网站,全景效果图如何制作,公司建网站制作平台,网站建设公司的介绍协程
协程是 Unity 内置的异步机制#xff0c;通过 yield 暂停执行#xff0c;实现任务在多帧中分段执行。与普通函数不同#xff0c;协程可在执行过程中挂起和恢复#xff0c;呈现并发效果#xff0c;但本质上仍运行于主线程。若在协程中进行耗时操作#…协程
协程是 Unity 内置的异步机制通过 yield 暂停执行实现任务在多帧中分段执行。与普通函数不同协程可在执行过程中挂起和恢复呈现并发效果但本质上仍运行于主线程。若在协程中进行耗时操作仍会导致主线程阻塞。因此协程更适合处理异步事件的调度而非需要多线程计算的任务。
StartCoroutine() 是启动器不是执行体yield return StartCoroutine() 是等待子协程完成的声明Unity协程调度器在背后管理执行流程
优势
使用简洁在需要处理耗时的异步操作如等待 HTTP 传输、资源加载、文件 I/O时官方建议优先考虑协程。Unity 生命周期集成协程由MonoBehaviour管理随脚本或对象生命周期自动中止。比如当GameObject被停用或销毁时其上运行的协程也会停止。无需线程切换协程运行在 Unity 主线程不必担心线程安全因为代码始终在主线程执行。
劣势
依赖 MonoBehaviour无法直接获取返回值协程返回类型为IEnumerator无法直接提供结果。通常需通过回调、全局状态或等待协程结束来获取数据不如TaskT直接。错误处理复杂在协程内不能直接使用try/catch捕获包含yield的代码块中的异常这使得异常处理更加困难。未处理的异常可能导致游戏逻辑问题被掩盖。性能与GC开销尽管单个协程开销小但大量协程会增加垃圾回收压力并可能影响帧率如装箱迭代器、WaitForSeconds等对象尤其是在每帧更新后统一调度时。每次 yield 都产生新对象。
使用场景
需要按照顺序执行、需要暂停、运行比单个帧花费时间更长的操作。
将对象移动到某个位置。为对象提供要执行的任务列表。淡入淡出视觉或音频。等待资源加载如Resources.LoadAsync/SceneManager.LoadSceneAsync。网络请求封装先 UnityWebRequest.SendWebRequest()然后yield return request 等待请求完成再检查结果。
yield return
Yield 表示该方法是一个迭代器 (IEnumerator)它将在多个帧上执行而 return 与常规函数一样在该点终止执行并将控制权传递回调用方法。
不同之处在于对于协程Unity 知道从上次中断的地方继续该方法。yield return 后面的内容将指定 Unity 在继续之前将等待多长时间。
yield return null - 等待下一帧yield return new WaitForSeconds(秒数) - 等待一段时间
对于重复延迟可以创建一个对象优化性能。
WaitForSeconds delay new WaitForSeconds(1); // 创建对象Coroutine coroutine;void Start(){StartCoroutine(MyCoroutine);}IEnumerator MyCoroutine(){int i 100;while (i 0){// Do something 100 timesi--;yield return delay; // 使用对象}// All Done!}yield return new WaitForSecondsRealtime(秒数) - 实时等待秒数yield return new WaitUntil(条件)/WaitWhile(条件) - 等待委托 yield return new WaitUntil(() condition) → 等待条件成立yield return new WaitWhile(() condition) → 等待条件不再成立
1. 用外部函数
yield return new WaitUntil(IsEmpty);
bool void IsEmpty()
{...//返回true或false
}2. 用lambda表达式
IEnumerator CheckFuel()
{yield return new WaitWhile(() fuel 0);...
}yield return new WaitForEndOfFrame() - 等待帧结束 会等到 Unity 渲染完每个 Camera 和 UI 元素然后再实际显示帧。这方面的典型用途是截取屏幕截图。yield return StartCoroutine()- 等待另一个协程
void Start(){// 启动协程StartCoroutine(MyCoroutine());}IEnumerator MyCoroutine(){// 启动等待第二个协程yield return StartCoroutine(MyOtherCoroutine());}IEnumerator MyOtherCoroutine(){...yield return new WaitForSeconds(1);}结束协程
yield break - 在协程完成前结束协程StopCoroutine - 在协程外部停止协程
bool stopCoroutine;
Coroutine runningCoroutine;void Start(){runningCoroutine StartCoroutine(MyCoroutine());}void Update(){if (stopCoroutine true){StopCoroutine(runningCoroutine);stopCoroutine false;}}IEnumerator MyCoroutine(){// Coroutine stuff...}StopAllCoroutines()- 停止MonoBehaviour上的所有协程 需要从启动它们的行为中调用 。
其他
推荐网址介绍
Async
async 关键字用于定义异步方法配合 await 使用可以在不阻塞Unity主线程的情况下执行耗时任务如网络请求、文件I/O从而使主线程保持流畅。
优势
和同步代码结构类似有线性的代码执行流程并且支持直接返回值。错误处理方便可以用try-catch捕捉错误处理。高效的任务组合内置并行处理机制
var task1 LoadPlayerDataAsync();
var task2 LoadLevelDataAsync();await Task.WhenAll(task1, task2); // 并行等待性能优化状态机更轻量特别是配合 UniTask更少的 GC 压力。
劣势
Unity 集成问题需要处理线程上下文时间控制复杂默认不受 Time.timeScale 影响需要手动实现游戏时间等待生命周期管理复杂需要手动取消任务
使用场景
网络请求和 I/O 操作复杂异步逻辑组合后台线程和 CPU 密集型任务需要精细错误处理的场景
关键字
Task表示一个异步操作用于执行异步任务并返回结果。async 关键字用于修饰方法表明该方法是异步的可以使用 await 进行异步调用。await 关键字用于等待异步操作完成避免阻塞主线程。异步方法在碰到await表达式之前都是使用同步的方式执行。
对比
异步加载资源对比
IEnumerator LoadAssetsCoroutine()
{// 顺序加载ResourceRequest request1 Resources.LoadAsyncTexture(Texture1);yield return request1;ResourceRequest request2 Resources.LoadAsyncTexture(Texture2);yield return request2;// 并行加载有限支持ResourceRequest[] requests new ResourceRequest[3];for (int i 0; i 3; i) {requests[i] Resources.LoadAsyncGameObject($Prefab_{i});}// 手动等待所有完成while (requests.Any(r !r.isDone)) {yield return null;}Debug.Log(All assets loaded);
}async Task LoadAssetsAsync()
{// 顺序加载var texture1 await Resources.LoadAsyncTexture(Texture1).AsTask();var texture2 await Resources.LoadAsyncTexture(Texture2).AsTask();// 并行加载var loadTasks new ListTask();for (int i 0; i 3; i) {loadTasks.Add(Resources.LoadAsyncGameObject($Prefab_{i}).AsTask());}await Task.WhenAll(loadTasks);Debug.Log(All assets loaded);
}代码结构与可读性对比
async/await 允许按照同步代码的思维方式编写异步逻辑可以直接返回值像同步方法一样调用其他异步方法。
IEnumerator LoadGameData()
{// 1. 加载玩家数据UnityWebRequest playerReq UnityWebRequest.Get(playerDataURL);yield return playerReq.SendWebRequest();PlayerData player JsonUtility.FromJsonPlayerData(playerReq.downloadHandler.text);// 2. 加载关卡数据UnityWebRequest levelReq UnityWebRequest.Get(levelDataURL);yield return levelReq.SendWebRequest();LevelData level JsonUtility.FromJsonLevelData(levelReq.downloadHandler.text);// 3. 初始化游戏InitializeGame(player, level);
}async Task LoadGameDataAsync()
{// 1. 加载玩家数据PlayerData player await LoadPlayerDataAsync();// 2. 加载关卡数据LevelData level await LoadLevelDataAsync();// 3. 初始化游戏InitializeGame(player, level);
}async TaskPlayerData LoadPlayerDataAsync()
{UnityWebRequest req UnityWebRequest.Get(playerDataURL);await req.SendWebRequest();return JsonUtility.FromJsonPlayerData(req.downloadHandler.text);
}