Unity 之 关于停止协程的五种方式解析

举报
陈言必行 发表于 2021/08/13 22:20:21 2021/08/13
【摘要】 Unity 之 关于停止协程的五种方式解析 前言:了解协程方式一:函数的方式方式二:函数名的方式方式三:接收返回值方式四:StopAllCoroutines方式五:禁用/销毁游戏对象本文小结: 前言:了解协程 官方描述 调用函数时,函数将运行到完成状态,然后返回。这实际上意味着在函数中发生的任何动作都必须在单帧更新内发生;函数调用不能用于包含程序性动画或...

前言:了解协程

官方描述 调用函数时,函数将运行到完成状态,然后返回。这实际上意味着在函数中发生的任何动作都必须在单帧更新内发生;函数调用不能用于包含程序性动画或随时间推移的一系列事件。

协程是一个可暂停执行 (yield) 直到给定的 YieldInstruction 达到完成状态的函数。

协程的不同用法:

  • yield 在下一帧上调用所有 Update 函数后,协程将继续。
  • yield WaitForSeconds 在为帧调用所有 Update 函数后,在指定的时间延迟后继续协程
  • yield WaitForFixedUpdate 在所有脚本上调用所有 FixedUpdate 后继续协程
  • yield WWW 在 WWW 下载完成后继续。
  • yield StartCoroutine 将协程链接起来,并会等待 MyFunc 协程先完成。

协程的误用:

  • 如果一个协程几乎每帧都运行并且在长时间运行操作中不会暂停,那么用 Update 或 LateUpdate 回调来替换该协程通常更合理一些。例如长时间运行或无限循环的协程。
  • 尽可能的减少嵌套使用:虽然嵌套的协程非常有利于确保代码的条理性和进行维护,但协程跟踪对象本身会导致产生更高的内存开销。

方式一:函数的方式

使用传递函数的方式来 开启协程:

StartCoroutine(Cor_1());

  
 
  • 1

停止协程:(❎ 错误的使用方式1)

StopCoroutine(Cor_1());

  
 
  • 1

最初学习的时候就这么干的,但是不知道为什么就是不好用。后来才明白:虽然传递的是一样的函数名,但是停止时传递进去的并不是开始时传递的函数的地址啊~。

停止协程:(❎ 错误的使用方式2)

StopCoroutine(”Cor_1“);

  
 
  • 1

新手的错误用法:使用传递函数的方式开启协程,使用传递字符串的形式停止协程。

那么使用StartCoroutine(Cor_1());这种方式开启协程,要如何才能手动停掉它呢?请继续往下看…


方式二:函数名的方式

使用传递函数名的方式 开启协程:

StartCoroutine("Cor_1");

  
 
  • 1

停止协程:

StopCoroutine(”Cor_1“);

  
 
  • 1

这样使用是没问题的(我猜测是内部是实现是通过<Key, Value>的形式保存了一下)。

缺点:只支持传递一个参数

由一,二得出结论,只有通过函数名的形式开启和关闭是可行的,但是这并没有解决我们方式一中留下的问题,请继续往下看吧…


方式三:接收返回值

不管使用下面哪种方式启动协程,都可以结束其返回值用以停止对应协程;

private Coroutine stopCor_1;
private Coroutine stopCor_2;

stopCor_1 = StartCoroutine("Cor_1");
stopCor_2 = StartCoroutine(Cor_2());

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

停止协程:

StopCoroutine(stopCor_1);
StopCoroutine(stopCor_2); 

  
 
  • 1
  • 2

使用这种接收返回值的方式就可以根据我们的需求来停止协程了;
这就解决了方式一,二中留下的问题。


方式四:StopAllCoroutines

任意一种方式开始协程

StartCoroutine("Cor_1");
StartCoroutine(Cor_2());

  
 
  • 1
  • 2

都可以使用StopAllCoroutines去停止

StopAllCoroutines();

  
 
  • 1

StopAllCoroutines() 可以停止当前脚本中所有协程。

注意事项:

  • 建议谨慎使用,因为可能后续修改逻辑时新建协程,在不需要被停止的情况下停止(别问我怎么知道的)
  • 需要确定调用脚本的全部协程都需要被终止(比如:断线重连需要重置所有状态)

方式五:禁用/销毁游戏对象

注意是:

gameObject.SetActive(false); 
//通过销毁游戏对象方式和禁用同效果
//Destroy(gameobject)

  
 
  • 1
  • 2
  • 3

不是这个:

script.enabled = false; 

  
 
  • 1

也就是隐藏脚本所挂载的游戏物体(其父物体被隐藏时也是一样),如下图:
5.1.1
当物体被再次激活时,协程不会继续执行


本文小结:

  1. 使用 StartCoroutine(函数()); 形式开启的,只能用接收返回值的形式去停止;【不限制参数个数】
  2. 使用 StartCoroutine(“函数名”); 形式开启的,可以使用 StopCoroutine(“函数名”); 形式停止, 也可使用 接收返回值的形式去停止。【缺点:只可以传递一个参数】
  3. 两种开启形式均受到 StopAllCoroutines() 控制。StopAllCoroutines() 可以停止当前脚本中所有协程。
  4. gameObject.SetActive(false); 可停掉所有此GameObject上的所有协程,且再次激活时协程不会继续。
  5. StopCoroutine(函数()); 脚本.enabled = false; 不可停掉协程。

文章来源: czhenya.blog.csdn.net,作者:陈言必行,版权归原作者所有,如需转载,请联系作者。

原文链接:czhenya.blog.csdn.net/article/details/115936459

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。