当前位置:首页 > 技术 > 正文内容

Unity中C#协程机制深度解析

访客 技术 2026年6月9日 1

协程的基本概念

在Unity游戏开发中,协程(Coroutines)是一种非常实用的异步编程工具。它允许我们在主线程中分阶段执行一段逻辑,而不会阻塞整个程序的运行。虽然协程看起来像是多线程操作,但实际上它运行在主线程上,通过"暂停-恢复"机制实现类似异步的效果。

与多线程的对比

多线程是指操作系统层面同时运行多个线程,每个线程独立执行任务。系统会将CPU时间划分为极小的时间片,轮流分配给各个线程,从而实现并发假象。这种方式适合处理耗时操作如网络请求或文件读写。

然而,多线程存在数据竞争问题。例如两个线程同时对一个变量进行增减操作,若没有加锁保护,最终结果可能不符合预期。虽然可以通过互斥量等机制解决,但会增加复杂性和性能开销。

协程的工作方式

协程本质上是用户控制的轻量级"伪并行"机制。它在同一主线程内运行,由开发者显式指定挂起点(yield语句),在下一帧或满足特定条件时继续执行。由于其执行粒度较大且由代码明确控制,避免了多线程常见的竞态条件。

IEnumerator CalculateSum()
{
    int result = 0;
    for (int i = 0; i < 1000; i++)
    {
        result += i;
        yield return null; // 暂停执行,下一帧恢复
    }
    Debug.Log("计算完成: " + result);
}

典型应用场景

协程特别适用于需要延时、分步执行的任务,比如:

  • 延迟调用某个方法
  • 渐进式加载资源
  • 动画序列控制
  • 定时刷新UI

传统做法可能使用Update中的计时器判断,但使用协程更清晰直观:

IEnumerator DelayedAction()
{
    float elapsed = 0f;
    while (elapsed < 3f)
    {
        elapsed += Time.deltaTime;
        yield return null;
    }
    Debug.Log("三秒已过");
}

Unity提供了WaitForSeconds类来简化这一过程:

IEnumerator SimpleDelay()
{
    yield return new WaitForSeconds(3f);
    Debug.Log("三秒后触发");
}

协程的启动与管理

通过StartCoroutine方法可以开启协程,支持两种形式:

// 方式一:传入IEnumerator对象
StartCoroutine(MyCoroutine());

// 方式二:传入方法名字符串(不推荐)
StartCoroutine("MyCoroutine");

终止协程可通过以下方法:

// 停止指定协程(仅限字符串方式启动)
StopCoroutine("MyCoroutine");

// 停止所有协程
StopAllCoroutines();

常用的挂起类型

  • yield return null; —— 下一帧恢复
  • yield return new WaitForSeconds(sec); —— 等待指定秒数
  • yield return new WaitForEndOfFrame(); —— 渲染结束后恢复
  • yield return new WaitForFixedUpdate(); —— 下一个物理更新周期恢复
  • yield return StartCoroutine(another); —— 等待另一个协程结束
  • yield break; —— 提前退出协程

底层执行原理

协程函数必须返回IEnumerator接口类型。该接口包含两个核心成员:

  • Current:获取当前迭代值
  • MoveNext():推进到下一步,返回bool表示是否可继续

每次遇到yield return时,Unity会在每帧调用MoveNext()尝试推进协程。如果返回true,则从上次中断处继续执行;若为false,则协程结束。

例如:

IEnumerator Example()
{
    Debug.Log("第一步");
    yield return null;
    Debug.Log("第二步");
    yield return new WaitForSeconds(1f);
    Debug.Log("第三步");
}

上述协程会在第一帧输出"第一步",第二帧输出"第二步",再等待一秒后输出"第三步"。

标签: UnityC#协程

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。