协程结束——实测

协程生命周期核心规则

协程是在 MonoBehaviour 实例 上运行的。它的生命周期依赖于该 MonoBehaviour 的 活动状态 以及 GameObject 的状态


物体设置

每个物体均挂载测试脚本


1. 正常结束 ✅ 会结束

  • 协程执行完最后一个 yield,方法自然返回 → 正常结束

  • 这是最常规的情况。


2. 所在 MonoBehaviour 被禁用 ❌ 不会结束

复制代码

一秒记录一次,第二秒暂停脚本,协程仍在运行

结果 :协程仍然会继续运行,不会结束。

⚠️ 重要enabled = false 只禁用 UpdateFixedUpdateLateUpdate 等生命周期方法,对协程没有影响 。协程独立于 enabled 状态运行。

一直在运行->update标识,后续就没有输出了


3. 所在 GameObject 被禁用 ❌ 不会结束?(需要分情况)

立即被禁用

没有继续了

重新开启

结果

GameObject 被禁用后 协程行为
立即被禁用 协程会暂停 ,但不会结束
稍后重新激活 协程从中断的地方继续执行????测试尚未恢复运行

⚠️ 关键点 :GameObject 被禁用后,协程不会运行 ,但协程状态被保留。重新激活后,协程会从上次 yield 的位置继续。


4. 所在 GameObject 被销毁 ✅ 会结束(被强制终止)

结果 :协程立即被终止,不会再执行任何代码。(第二秒终止,所有的都没有输出了)

Destroy(gameObject)Destroy(this) 被调用时,Unity 会清理该 MonoBehaviour 上所有正在运行的协程。


5. 场景切换 ✅ 会结束(除非特殊标记)

结果

场景切换方式 协程行为
SceneManager.LoadScene() 协程被终止
SceneManager.LoadSceneAsync() 协程被终止
加载时标记 DontDestroyOnLoad 的对象 ✅ 协程继续运行(因为对象没有被销毁)

⚠️ 场景切换时,未标记 DontDestroyOnLoad 的所有 GameObject 都会被销毁,因此其上的协程自然被终止。


6. 调用 StopCoroutine / StopAllCoroutines ✅ 会结束

结果 :协程立即被终止,不会继续执行。

注意:StopCoroutine(string methodName) 也可以停止,但推荐使用 Coroutine 对象的方式,避免重名问题。


完整总结表

场景 协程是否会结束 备注
1. 正常执行完毕 ✅ 结束 自然返回
2. MonoBehaviour 禁用 (enabled = false) 不会结束 协程独立于 enabled 运行
3. GameObject 禁用 (SetActive(false)) 但暂停
4. GameObject 销毁 (Destroy) 强制终止 协程被清理
5. 场景切换(未标记 DontDestroyOnLoad) 强制终止 对象被销毁
6. 调用 StopCoroutine / StopAllCoroutines 强制终止 手动停止

常见避坑建议

坑 1:以为禁用脚本就能停止协程

复制代码
enabled = false; // 协程还在跑!

正确做法 :需要停止协程时,显式调用 StopCoroutineStopAllCoroutines

坑 2:尚未切换开启的协程

  • 每次调用 Coroutinee(),都会创建一个全新的、未启动的协程实例
  • StopCoroutine 收到的,只是这个 "新创建的、没跑过的协程",而不是你之前 StartCoroutine 启动的那个
  • 结果就是:你停的是一个不存在的东西,原来的协程还在后台跑,完全不受影响

所以要接收,调用指定协程

代码

cs 复制代码
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;

public class TestCooroutine : MonoBehaviour
{
    public string goName;
    public TestCooroutine testCooroutine;
    public Coroutine thisCoroutine;

    private void Start()
    {
        goName = gameObject.name;
        thisCoroutine = StartCoroutine(Coroutinee());
        testCooroutine = GetComponent<TestCooroutine>();
    }


    private void Update()
    {
        // Debug.Log("一直在运行奥");
        if (Input.GetKeyDown(KeyCode.Q))
        {
            testCooroutine.enabled = false;
        }
        else if (Input.GetKeyDown(KeyCode.W))
        {
            gameObject.SetActive(false); // 禁用整个 GameObject
        }
        else if (Input.GetKeyDown(KeyCode.E))
        {
            Destroy(gameObject); // 销毁 GameObject
        }
        else if (Input.GetKeyDown(KeyCode.R))
        {
            StopCoroutine(Coroutinee());
        }
        else if(Input.GetKeyDown(KeyCode.T))
        {
            SceneManager.LoadScene("Test2");
        }
        else if (Input.GetKeyDown(KeyCode.Y))
        {
            enabled = false;
        }
        else if (Input.GetKeyDown(KeyCode.U))
        {
             StopAllCoroutines();
        }
        else if (Input.GetKeyDown(KeyCode.I))
        {
            StopCoroutine(thisCoroutine);
        }
        
    }

    IEnumerator Coroutinee()
    {
        int circle = 15;
        while (circle > 0)
        {
            Debug.Log(goName + ":" + circle--);
            yield return new WaitForSeconds(1);
        }
        Debug.Log(goName+"已结束正常并退出");
    }
}
cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Test2 : MonoBehaviour
{
    private List<GameObject> _go;
    private void Start()
    {
        var test = FindObjectsOfType<TestCooroutine>().ToList();
        _go = test.Select(x => x.gameObject).ToList();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            for (int i = 0; i < _go.Count; i++)
            {
                _go[i].SetActive(true);
            }
            Debug.Log("恢复了");
        }
    }
}
相关推荐
z落落2 分钟前
C# ArrayList 动态集合(接口/区别/API/深浅拷贝)+ List<T> 泛型集合
开发语言·c#
Cx330❀2 分钟前
【Linux网络】从零构建高性能UDP服务器:从Echo到英译汉业务级实现
大数据·linux·服务器·开发语言·网络·c++·udp
basketball6163 分钟前
Golang:基础语法总结
开发语言·后端·golang
兰令水4 分钟前
leecodecode【双指针题2】【2026.5.26打卡-java版本】
java·开发语言·算法
不吃土豆的马铃薯5 分钟前
TCP 三次握手 / 四次挥手详解
服务器·开发语言·网络·c++·网络协议·tcp/ip
WMX10126 分钟前
Unity-shader学习记录
学习·unity·游戏引擎
ch.ju6 分钟前
Java程序设计(第3版)第四章——引用
java·开发语言
Huangjin007_10 分钟前
【C++ STL篇(十三)】无序关联容器 unordered_set / unordered_map解析
开发语言·c++
白日与明月10 分钟前
pip下载库指定操作系统及python版本
开发语言·python·pip
WMX101211 分钟前
Hololens 2 上部署 Unity+MRTK 项目_模型着色
unity·游戏引擎·hololens