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 完成后直接唤醒,继续执行剩余逻辑。
- 可以通过
StopCoroutine
或 StopAllCoroutines
控制协程生命周期。
6. 协程注意事项
- 不可用于精确时间控制:帧率不稳定会影响时间判断。
- 避免长期阻塞:协程内部最好不要进行 CPU 密集型计算。
- 嵌套协程管理:
yield return StartCoroutine(...)
会等待子协程完成。
- 异常处理:协程内部异常不会自动抛出到主线程,需要 try-catch。