网站分站系,工程交易中心,仿美团外卖小程序源码,网站 支持建设单位Unity的协程#xff08;Coroutine#xff09;是一种异步编程的机制#xff0c;允许在多个帧之间分割代码的执行#xff0c;而不阻塞主线程。与传统的多线程不同#xff0c;Unity的协程在主线程中运行#xff0c;并不会开启新的线程。
什么是协程#xff1f;
协程是一种…Unity的协程Coroutine是一种异步编程的机制允许在多个帧之间分割代码的执行而不阻塞主线程。与传统的多线程不同Unity的协程在主线程中运行并不会开启新的线程。
什么是协程
协程是一种能在一定条件下暂停执行并在稍后恢复执行的函数。它允许将一个任务拆分为多个小任务每一小段任务可以在多个帧内完成而不是在一帧内阻塞主线程。
在Unity中协程通过StartCoroutine方法启动并可以通过yield关键字来暂停执行直到满足特定条件例如等待时间、等待帧、等待另一个协程完成等后继续运行。
协程的语法
在Unity中协程的基本语法如下
using UnityEngine;
using System.Collections;public class CoroutineExample : MonoBehaviour
{void Start(){// 启动一个协程StartCoroutine(MyCoroutine());}IEnumerator MyCoroutine(){Debug.Log(第1步: 开始协程);// 等待3秒yield return new WaitForSeconds(3);Debug.Log(第2步: 等待3秒完成);// 等待一帧yield return null;Debug.Log(第3步: 等待一帧完成);// 等待直到某个条件为真yield return new WaitUntil(() Time.time 5);Debug.Log(第4步: 等待直到Time.time 5);}
}
StartCoroutine(MyCoroutine())启动一个协程执行MyCoroutine()函数。yield return new WaitForSeconds(3)暂停执行等待3秒后恢复执行。yield return null暂停当前协程等到下一帧再恢复执行。yield return new WaitUntil(() Time.time 5)暂停直到Time.time 5为true时恢复执行。
启动和停止协程
启动协程
StartCoroutine(“方法名”)使用字符串指定协程名称。 StartCoroutine(方法())传递协程的IEnumerator方法。 示例
StartCoroutine(MyCoroutine);
StartCoroutine(MyCoroutine());
停止协程
StopCoroutine(方法名或引用)停止指定的协程。 StopAllCoroutines()停止脚本中所有正在运行的协程。
Coroutine myCoroutine;void Start()
{myCoroutine StartCoroutine(MyCoroutine());
}void StopIt()
{StopCoroutine(myCoroutine); // 停止指定的协程StopAllCoroutines(); // 停止当前脚本中的所有协程
}
注意使用StopCoroutine时不能使用StartCoroutine(“MyCoroutine”)的字符串方式因为无法引用该协程。
协程的yield语法详解
yield的作用是暂停当前协程的执行直到指定的条件满足。Unity中常见的yield操作有
yield return null; 等待一帧yield return new WaitForSeconds(t); 等待t秒yield return new WaitUntil(predicate); 等待直到条件为真yield return new WaitWhile(predicate); 等待直到条件为假yield return StartCoroutine(协程); 等待另一个协程完成yield break; 终止协程立即退出
常见的协程应用场景
场景切换中的加载动画
在场景加载的过程中显示加载动画而不是卡顿的黑屏。
IEnumerator LoadSceneAsync()
{AsyncOperation operation SceneManager.LoadSceneAsync(SceneName);while (!operation.isDone){Debug.Log($加载进度{operation.progress * 100}%);yield return null; // 等待一帧}Debug.Log(场景加载完成);
}
动画和特效的控制
在播放一段动画或特效时等待动画播放完成再继续后续操作。
IEnumerator PlayAnimation()
{Animator animator GetComponentAnimator();animator.Play(Attack);yield return new WaitForSeconds(2); // 等待动画播放2秒Debug.Log(动画播放完成执行其他操作);
}
定时触发的任务
IEnumerator SpawnEnemies()
{while (true){Instantiate(enemyPrefab, transform.position, Quaternion.identity);yield return new WaitForSeconds(5); // 每隔5秒刷怪}
}
协程和多线程的区别
协程多线程运行在主线程中每个线程有独立的执行流使用yield暂停使用Thread.Sleep等不需要上下文切换效率高需要操作系统的线程调度性能开销大主要用于异步逻辑操作主要用于计算密集型操作
注意事项和最佳实践
不要阻塞主线程协程在主线程中运行while(true)的无限循环会冻结游戏。避免频繁调用StartCoroutine如果在Update中频繁调用StartCoroutine会导致性能下降。避免内存泄漏未手动停止的协程会一直运行导致内存泄漏。可用StopCoroutine来手动控制协程的停止。不要用字符串调用协程StartCoroutine(“MyCoroutine”)的方式不易调试和管理建议使用StartCoroutine(MyCoroutine())。不要滥用协程协程适用于需要在多个帧内分段执行的任务。对于简单的帧内任务尽量不要使用协程。
Unity的协程机制提供了一种轻量的异步任务调度适合在游戏中实现等待、计时、加载动画、场景切换等操作。与多线程相比协程的运行成本更低控制也更简单。通过yield来暂停和恢复代码执行可以显著提高游戏性能和玩家体验。合理使用协程有助于优化游戏中的异步任务。
Unity是如何实现协程的
Unity的协程原理基于迭代器Iterator和C#的IEnumerator接口而不是多线程。Unity的协程并不会新开一个线程去执行逻辑而是在主线程中调度通过“分段执行”的方式控制代码的暂停和恢复。
协程的原理概述
C#中的迭代器和yield return
协程的本质是C#的迭代器Iterator而yield return就是一种控制流的中断标志。当执行到yield return时Unity会将当前协程的“状态”保存起来并在下一个“可用的时机”恢复执行。
Unity的调度器Coroutine Scheduler
Unity每一帧都会检查哪些协程需要恢复执行。如果一个协程调用了yield return WaitForSeconds(2)Unity会在2秒后恢复该协程并从上次中断的位置继续执行。这种调度机制与多线程无关一切都在主线程中运行。
执行流程
Unity的MonoBehaviour管理协程通过内部的队列/列表维护所有活跃的协程。每一帧Unity会遍历这些协程检查是否满足“恢复执行”的条件如时间已到、等待的条件达成等。如果条件满足Unity会调用该协程的MoveNext()方法让协程继续运行直到遇到下一个yield语句。
协程的实现细节
要理解Unity如何实现协程必须先掌握C#的IEnumerator和yield return的机制。
C# 的 IEnumerator 和 yield return 当在C#中使用yield return时编译器会自动将方法“拆分”成状态机State Machine而这个状态机可以跟踪函数的当前执行位置。 示例如下
IEnumerator MyCoroutine()
{Debug.Log(第1步);yield return new WaitForSeconds(1); // 暂停1秒Debug.Log(第2步);yield return new WaitForSeconds(2); // 暂停2秒Debug.Log(第3步);
}
编译器生成的等价状态机代码如下简化版省略了复杂的状态机细节
public class MyCoroutineStateMachine : IEnumerator
{private int state 0; // 用于跟踪当前执行到的位置public object Current { get; private set; } // yield返回的内容public bool MoveNext(){switch (state){case 0:Debug.Log(第1步);Current new WaitForSeconds(1);state 1;return true; // 表示协程还没有结束case 1:Debug.Log(第2步);Current new WaitForSeconds(2);state 2;return true;case 2:Debug.Log(第3步);state -1; // 表示协程结束return false;}return false;}public void Reset() { }
}
解释
state控制当前协程的“步骤状态”state0表示正在执行第1步state1表示执行第2步。Current表示yield return的结果如WaitForSeconds(1)。MoveNext()每当Unity的调度器在新一帧时调用MoveNext()协程的控制流就会跳转到当前的state位置。当state为-1时协程结束MoveNext()返回false。 这段代码表明Unity通过“状态机 迭代器”的机制将协程拆分成多个小的执行步骤这些步骤会在每一帧内被调度器分阶段运行。
Unity的调度器 (Scheduler)
Unity在每一帧都会遍历所有的协程并调用每个协程的MoveNext()方法。如果MoveNext()返回trueUnity会继续等待否则Unity将把这个协程从队列中删除。Unity在执行MoveNext()时会检查Current的返回值 如果是null表示立即恢复继续执行如果是WaitForSecondsUnity会记录当前的“等待时间”然后延迟恢复协程。如果是CustomYieldInstruction例如yield return new WaitUntil()Unity会检测其条件是否满足。
Unity的协程工作流程图
[Unity Start] ↓
[协程被添加到队列] ↓
[每一帧调用协程的MoveNext()] ↓
[检测Current] └─ 如果是 WaitForSeconds等待指定时间└─ 如果是 WaitUntil/WaitWhile检查条件└─ 如果是 null直接继续执行↓
[如果协程结束则从队列中移除]
小结
Unity的协程依赖C#的迭代器通过IEnumerator生成的状态机来分段执行代码。 Unity的调度器每一帧都会检查和恢复协程基于Current的结果来决定是否继续执行。 协程不会并行执行只是在主线程上“暂停-恢复”代码。