关闭Unity Coroutine的正确姿势

本文探讨了Unity中Coroutine(协程)的正确使用方法,特别是如何停止协程。介绍了几种启动与停止协程的方法,并通过实验验证了它们的有效性。推荐使用Coroutine对象来停止协程,以确保更广泛的兼容性和更好的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Coroutine(协程)作为Unity引擎中的一项有用的特性,在开发中带给我们了很多帮助,但在使用过程中,有一个新人或没有仔细阅读文档的开发者常犯的错误。那就是使用了错误的姿势来StopCoroutine,下面我来进行一番演示:

创建一个脚本:

public class TestCoroutine : MonoBehaviour
{
    IEnumerator CoroutineMethod()
    {
        while (true)
        {
            Debug.Log("Coroutine is running...");
            yield return new WaitForSeconds(1);
        }        
    }
}

有一个每秒打印消息的协程。下面是几种开起的写法:

public void StartCoroutineWithString()
{
    StartCoroutine("CoroutineMethod");
}

public void StartCoroutineWithEnumerator1()
{
    StartCoroutine(CoroutineMethod());
}

public void StartCoroutineWithEnumerator2()
{
    _runningItor = CoroutineMethod();
    StartCoroutine(_runningItor);
}

以及几种关闭的写法:

public void StopCoroutineWithString()
{
    StopCoroutine("CoroutineMethod");
}
    
public void StopCoroutineWithEnumerator1()
{
    StopCoroutine(CoroutineMethod());
}

public void StopCoroutineWithEnumerator2()
{
    if (_runningItor != null)
    {
        StopCoroutine(_runningItor);
        _runningItor = null;
    }        
}

我使用了一个UI进行测试:


读者可先思考一下每种开起方法的关闭方法...

...

...

...

...

下面公布我的测试结果

 StopWIthStringStopWithEnumerator1StopWithEnumerator2
StartWithStringYESNONO
StartWithEnumerator1NONONO
StartWithEnumerator2NONOYES

有没有一点suprise??没有的话你就是合格的开发者XD。上面的结果表明,以函数名字符串为参数开起的协程,可以用函数名字符串的形式关闭,可以猜想出,在开启时Unity通过反射获取到成员函数,然后将IEnumerator与函数名建立映射。在关闭时用函数名获取IEnumerator,再关闭。StartWithEnumerator2就是该过程最直接的方式,通过IEnumerator来关闭。至于StartWithIEnumerator1为什么不能关闭?因为使用这样的方法:

StopCoroutine(CoroutineMethod());

是向StopCoroutine()传递了一个新的IEnumerator,并不是StartCoroutine()时传递的对象。因此Unity找不到你所指的是哪个协程。

其实Unity推荐的写法上面的都不是,StartCoroutine其实有一个类型是Coroutine的返回值:

public Coroutine StartCoroutine(IEnumerator routine);
public Coroutine StartCoroutine(string methodName, [DefaultValue("null")] object value);
public Coroutine StartCoroutine(string methodName);
使用
public void StopCoroutine(Coroutine routine);

可以关闭任意形式开起的协程。我们来修改下代码,将开起时返回的Coroutine保存下来,并添加一个使用Coroutine的关闭方法:

public void StartCoroutineWithString()
{
    _runningCoroutine = StartCoroutine("CoroutineMethod");
}

public void StartCoroutineWithEnumerator1()
{
    _runningCoroutine = StartCoroutine(CoroutineMethod());
}

public void StartCoroutineWithEnumerator2()
{
    _runningItor = CoroutineMethod();
    _runningCoroutine = StartCoroutine(_runningItor);
}
...
...
public void StopCoroutineWithCoroutineObj()
{
    if (_runningCoroutine != null)
    {
        StopCoroutine(_runningCoroutine);
        _runningCoroutine = null;
    }
}

更新测试UI:


测试结果不出所料:

 StopWithStringStopWithEnumerator1StopWithEnumerator2StopWithCoroutineObj
StartWithStringYESNONOYES
StartWithEnumerator1NONONOYES
StartWithEnumerator2NONOYESYES

使用Coroutine关闭协程的方式,兼容性广,效率佳,是上上之选!

本博客还很年轻,会不时发布一些Unity开发经验和有用的框架组件。读者有任何问题都可以向作者提问,欢迎大家踊跃参与!大家的鞭笞是我成长的动力!谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值