0%

Unity协程深入分析

1. 协程 vs Update 轮询

  • Update轮询:每帧主动检测状态,需要手动管理状态逻辑。
  • 协程 Coroutine:逻辑暂停,等待条件满足时 Unity 自动恢复执行。

核心区别对比

对比项 Update轮询 协程 Coroutine
检查方式 每帧自己 if 检查 yield return 后自动挂起
CPU开销 多对象轮询累积大 集中管理,开销小
写法复杂度 高,状态机逻辑复杂 低,顺序逻辑直观
可读性 差,容易出错 像同步代码,自然清晰
出错概率 高,容易漏判或重复判定 低,写完即能跑

一句话总结:协程让“等待”自动化,无需每帧检查。


2. Update 检测请求示例(传统方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private UnityWebRequest m_Request;

public void StartRequest(string url)
{
m_Request = UnityWebRequest.Get(url);
m_Request.SendWebRequest();
}

private void Update()
{
if (m_Request == null || !m_Request.isDone) return;

if (m_Request.result == UnityWebRequest.Result.ConnectionError ||
m_Request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Request Error: " + m_Request.error);
}
else
{
Debug.Log("Request Success: " + m_Request.downloadHandler.text);
}

m_Request = null;
}

缺点:Update 负担重,需要手动管理状态。


3. 协程检测请求示例(推荐方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void StartRequest(string url)
{
StartCoroutine(RequestCoroutine(url));
}

private IEnumerator RequestCoroutine(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
yield return request.SendWebRequest();

if (request.result == UnityWebRequest.Result.ConnectionError ||
request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Request Error: " + request.error);
}
else
{
Debug.Log("Request Success: " + request.downloadHandler.text);
}
}
}

优点:自动挂起等待,不用管理完成时机,逻辑自然顺序。


4. 协程使用场景总结

  • 等待 I/O 操作:网络请求、文件读取、WWW 请求等。
  • 动画控制:顺序播放动画或控制延迟。
  • 条件等待:等待某些状态触发,例如玩家进入区域或敌人死亡。
  • 循环任务:无需每帧 Update 手动判断。

5. 协程性能与调度机制

  • yield return 后,协程被挂起。
  • Unity 集中管理所有挂起的协程。
  • 每帧只需检查协程状态量,不会像多对象轮询消耗过多 CPU。
  • 条件满足或 I/O 完成后直接唤醒,继续执行剩余逻辑。
  • 可以通过 StopCoroutineStopAllCoroutines 控制协程生命周期。

6. 协程注意事项

  • 不可用于精确时间控制:帧率不稳定会影响时间判断。
  • 避免长期阻塞:协程内部最好不要进行 CPU 密集型计算。
  • 嵌套协程管理yield return StartCoroutine(...) 会等待子协程完成。
  • 异常处理:协程内部异常不会自动抛出到主线程,需要 try-catch。