欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > 请简述Unity中协程的原理

请简述Unity中协程的原理

2025/2/24 23:11:53 来源:https://blog.csdn.net/2303_76354097/article/details/145808173  浏览:    关键词:请简述Unity中协程的原理

在 Unity 中,协程(Coroutine)是一种特殊的函数,它可以暂停执行并在之后的某个时间点继续执行,这为开发者处理异步操作提供了便利。Unity 中的协程是一种基于迭代器模式实现的异步编程机制,它通过 yield return 语句暂停和继续执行,由协程管理器进行管理,为开发者提供了一种简单、高效的方式来处理异步操作。

目录

 1  协程的执行流程

 2  原理

 3  协程与线程的区别

 4  协程的使用案例


 1  协程的执行流程

协程本质上是一个返回类型为 IEnumerator 的方法,它可以包含一个或多个 yield return 语句。yield return 语句用于暂停协程的执行,并将控制权交还给调用者。当满足特定条件时,协程会从暂停的位置继续执行。

  • 启动协程:在 Unity 中,可以使用 StartCoroutine 方法来启动一个协程。当调用 StartCoroutine 时,Unity 会将协程加入到一个协程管理器中,协程开始执行,直到遇到第一个 yield return 语句。
  • 暂停执行:当协程遇到 yield return 语句时,它会暂停执行,并将控制权交还给调用者。yield return 后面可以跟不同的值,这些值决定了协程何时继续执行。例如:
    • yield return null:表示在下一帧继续执行协程。
    • yield return new WaitForSeconds(1):表示等待 1 秒后继续执行协程。
    • yield return new WaitForFixedUpdate():表示在下一次固定更新(FixedUpdate)之后继续执行协程。
  • 继续执行:当满足 yield return 语句指定的条件时,协程会从暂停的位置继续执行,直到遇到下一个 yield return 语句或协程结束。
  • 协程结束:当协程执行完所有代码,或者遇到 yield break 语句时,协程结束。

 2  原理

  • 迭代器模式:在 C# 中,协程是基于迭代器模式实现的。IEnumerator 接口定义了一个迭代器,它包含 MoveNext 方法和 Current 属性。当调用 StartCoroutine 时,Unity 会创建一个迭代器对象,并调用其 MoveNext 方法来执行协程的代码。当遇到 yield return 语句时,MoveNext 方法返回 true,并将 yield return 后面的值赋给 Current 属性。当协程结束时,MoveNext 方法返回 false

(迭代器模式(Iterator Pattern)是一种行为设计模式,它提供了一种方法来顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

抽象迭代器(Iterator):定义了访问和遍历元素的接口,通常包含 MoveNext 方法用于移动到下一个元素,Current 属性用于获取当前元素,Reset 方法用于将迭代器重置到初始位置。

具体迭代器(Concrete Iterator):实现了抽象迭代器接口,负责具体的元素遍历逻辑,它会维护一个指向当前元素的指针。

抽象聚合(Aggregate):定义了创建迭代器对象的接口,通常包含一个 CreateIterator 方法。

具体聚合(Concrete Aggregate):实现了抽象聚合接口,负责创建具体的迭代器对象。

  • 协程管理器:Unity 内部有一个协程管理器,负责管理所有正在运行的协程。在每一帧的更新循环中,协程管理器会检查每个协程的状态,根据 yield return 语句指定的条件决定是否继续执行协程。(协程管理器的主要职责就是跟踪协程的状态,根据 yield return 语句所设定的条件来决定何时继续执行协程。)

 3  协程与线程的区别

  • 线程:线程是操作系统调度的最小单位,多个线程可以并行执行,它们在不同的 CPU 核心上同时运行,因此可以充分利用多核处理器的性能。但是线程的创建和销毁开销较大,并且需要处理线程同步和锁的问题,容易出现死锁和数据竞争等问题。

(隐藏提问点:Unity中多线程执行哪些代码会报错?

Unity 的很多核心对象和组件是与主线程紧密绑定的,直接在多线程中对它们进行操作会报错。(直接操作 Unity 的主线程对象,例如:游戏对象(GameObject)相关操作,组件(Component)相关操作)

渲染相关的操作和 API 依赖于主线程和特定的渲染上下文,在多线程中访问会导致错误。( 访问 Unity 的渲染相关 API)调用 Unity 的生命周期方法,访问 Unity 的输入系统)

  • 协程:协程是在单线程中实现的,它通过 yield return 语句暂停和继续执行,不会像线程那样进行上下文切换,因此开销较小。协程主要用于处理异步操作,例如网络请求、动画播放等,避免阻塞主线程。

 4  协程的使用案例

        private void LoadAsyncCore<T>(string path, ResourcesLoadCallback<T> callBack = null, bool isTypeParam = false) where T : Object{string resName = (isTypeParam? path + "_type_" : path + "_") + typeof(T).Name;ResInfo<T> info = GetOrCreateResInfo<T>(resName);info.CallBack += callBack;info.Coroutines = MonoMgr.Instance.StartCoroutine(LoadAsyncCoroutine(path, info, isTypeParam));}private IEnumerator LoadAsyncCoroutine<T>(string path, ResInfo<T> info, bool isTypeParam = false) where T : Object{ResourceRequest res;yield return res=isTypeParam?Resources.LoadAsync(path, typeof(T)):Resources.LoadAsync<T>(path);info.Asset=isTypeParam?(T)res.asset:res.asset as T;if (info.RefCount == 0)UnLoadAsset<T>(path, false, null, false);else{info.CallBack?.Invoke(info.Asset);info.CallBack = null;info.Coroutines = null;}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词