协程的使用

请注意:这个关于协程的教程共有两部分,这是第二部分,如果您未曾看过第一部分——协程介绍,那么在阅读这部分内容之前建议您先了解一下。

计时器例子
第一个教程中,我们已经了解了协程如何让一个方法“暂停”下来,并且让它yield直到某些值到达我们给定的数值;并且利用它,我们还创建了一个很棒的计时器系统。协程一个很重要的内容是,它可以让普通的程序(比方说一个计时器)很容易地被抽象化并且被复用。

协程的参数
抽象化一个协程的第一个方法是给它传递参数,协程作为一个函数方法来说,它自然能够传递参数。这里有一个协程的例子,它在特定的地方输出了特定的信息。
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
Using UnityEngine;
Using System.Collections;
  
Public class TimerExample : MonoBehaviour
{
     Void Start()
     {
         //Log "Hello!" 5 times with 1 second between each log
         StartCoroutine(RepeatMessage(5, 1.0f, "Hello!" ));
     }
  
     IEnumerator RepeatMessage( int count, float frequency, string message)
     {
         for ( int i = 0; i < count; i++)
         {
             Debug.Log(message);
             for ( float timer = 0; timer < frequency; timer += Time.deltaTime)
                 Yield return 0;
              
         }
     }
}


嵌套的协程
在此之前,我们yield的时候总是用0(或者null),仅仅告诉程序在继续执行前等待下一帧。协程最强大的一个功能就是它们可以通过使用yield语句来相互嵌套。
眼见为实,我们先来创建一个简单的Wait()程序,不需要它做任何事,只需要在运行的时候等待一段时间就结束。
[C#]  纯文本查看  复制代码
?
1
2
3
4
5
IEnumerator Wait( float duration)
{
     for ( float timer = 0; timer < duration; timer += Time.deltaTime)
         Yield return 0;
}


接下来我们要编写另一个协程,如下:
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Using UnityEngine;
Using System.Collections;
  
Public class TimerExample : MonoBehaviour
{
     voidStart()
     {
         StartCoroutine(SaySomeThings());
     }
  
     //Say some messages separated by time
     IEnumerator SaySomeThings()
     {
         Debug.Log( "The routine has started" );
         Yield return StartCoroutine(Wait(1.0f));
         Debug.Log( "1 second has passed since the last message" );
         Yield return StartCoroutine(Wait(2.5f));
         Debug.Log( "2.5 seconds have passed since the last message" );
     }
  
     //Our wait function
     IEnumerator Wait( float duration)
     {
         for ( float timer = 0; timer < duration; timer += Time.deltaTime)
             Yield return 0;
     }
}


第二个方法用了yield,但它并没有用0或者null,而是用了Wait()来yield,这相当于是说,“不再继续执行本程序,直到Wait程序结束”。
现在,协程在程序设计方面的能力要开始展现了。

控制对象行为的例子
在最后一个例子中,我们就来看看协程如何像创建方便的计时器一样来控制对象行为。协程不仅仅可以使用可计数的时间来yield,它还能很巧妙地利用任何条件。将它与嵌套结合使用,你会得到控制游戏对象状态的最强大工具。

运动到某一位置
对于下面这个简单脚本组件,我们可以在Inspector面板中给targetPosition和moveSpeed变量赋值,程序运行的时候,该对象就会在协程的作用下,以我们给定的速度运动到给定的位置。
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
using UnityEngine;
Using System.Collections;
  
Public class MoveExample : MonoBehaviour
{
     Public Vector3 targetPosition;
     Public float moveSpeed;
  
     Void Start()
     {
         StartCoroutine(MoveToPosition(targetPosition));
     }
  
     IEnumerator MoveToPosition(Vector3 target)
     {
         while (transform.position != target)
         {
             transform.position = Vector3.MoveTowards(transform.position, target, moveSpeed * Time.deltaTime);
             Yield return 0;
         }
     }
}

这样,这个程序并没有通过一个计时器或者无限循环,而是根据对象是否到达指定位置来yield。

按指定路径前进
我们可以让运动到某一位置的程序做更多,不仅仅是一个指定位置,我们还可以通过数组来给它赋值更多的位置,通过MoveToPosition() ,我们可以让它在这些点之间持续运动。
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Using UnityEngine;
Using System.Collections;
  
Public class MoveExample : MonoBehaviour
{
     Public Vector3[] path;
     Public float moveSpeed;
  
     Void Start()
     {
         StartCoroutine(MoveOnPath( true ));
     }
  
     IEnumerator MoveOnPath( bool loop)
     {
         do
         {
             foreach (var point in path)
                 Yield return StartCoroutine(MoveToPosition(point));
         }
         while (loop);
     }
  
     IEnumerator MoveToPosition(Vector3 target)
     {
         while (transform.position != target)
         {
             transform.position = Vector3.MoveTowards(transform.position, target, moveSpeed * Time.deltaTime);
             Yield return 0;
         }
     }
}

我还加了一个布尔变量,你可以控制在对象运动到最后一个点时是否要进行循环。
把Wait()程序加进来,这样就能让我们的对象在某个点就可以选择是否暂停下来,就像一个正在巡逻的AI守卫一样,这真是锦上添花啊!

注意:
如果你刚接触协程,我希望这两个教程能帮助你了解它们是如何工作的,以及如何来使用它们。以下是一些在使用协程时须谨记的其他注意事项:
  • l 在程序中调用StopCoroutine()方法只能终止以字符串形式启动(开始)的协程;
  • l 多个协程可以同时运行,它们会根据各自的启动顺序来更新;
  • l 协程可以嵌套任意多层(在这个例子中我们只嵌套了一层);
  • l 如果你想让多个脚本访问一个协程,那么你可以定义静态的协程;
  • l 协程不是多线程(尽管它们看上去是这样的),它们运行在同一线程中,跟普通的脚本一样;
  • l 如果你的程序需要进行大量的计算,那么可以考虑在一个随时间进行的协程中处理它们;
  • l IEnumerator类型的方法不能带ref或者out型的参数,但可以带被传递的引用;
  • l 目前在Unity中没有简便的方法来检测作用于对象的协程数量以及具体是哪些协程作用在对象上。
如果您发现教程中存在问题和错误的信息,或者有任何建议又或者您想要在这里看到其他需要的教程,可以发 邮件或者在评论中留言。

作者ChevyRay 2013928日,snaker7译 原文地址:http://unitypatterns.com/scripting-with-coroutines/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
Unity中的协程使用分为两部分:协程本体和协程调度器。协程本体是使用C#的迭代器函数来实现的,它允许函数在中间暂停并返回。而协程调度器则利用了MonoBehaviour中的生命周期函数来实现分时调度。\[1\]\[2\] 在Unity中,协程使用有多种场景。首先,它可以用于异步加载资源,通过在协程中加载资源,可以避免阻塞主线程。其次,协程可以将一个复杂的程序分帧执行,使得程序的执行更加平滑。最后,协程还可以用作定时器,通过在协程中设置等待时间来实现定时功能。\[3\] 在使用协程时,需要注意一些事项。首先,协程只能在继承了MonoBehaviour的类中使用。其次,协程函数必须返回IEnumerator类型。另外,协程函数中可以使用yield语句来暂停执行,并指定下一次执行的时间或条件。最后,协程函数可以通过StopCoroutine函数来停止协程的执行。\[3\] 总结来说,Unity的协程使用是通过协程本体和协程调度器来实现的,协程本体使用C#的迭代器函数,协程调度器利用了MonoBehaviour的生命周期函数。协程使用场景包括异步加载资源、分帧执行复杂程序和定时器。在使用协程时需要注意一些事项,如只能在继承了MonoBehaviour的类中使用协程函数必须返回IEnumerator类型等。 #### 引用[.reference_title] - *1* *3* [【Unity】Unity协程(Coroutine)的原理与应用](https://blog.csdn.net/hafeiyangha/article/details/125365152)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Unity的协程详解](https://blog.csdn.net/vinkey_st/article/details/126759402)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值