理解Unity中的协程的使用
2015-01-28 08:30
225 查看
今天,换项目组以后,不用lable,想用下自己定制的数字,发现居然没人写。
那就把旧项目的东西拿过来,看了看源码,注意到了协程这货,而且最近同事也鼓励我们试试用协程,于是就来研究一下吧。
查了一些文档,以下是整理和总结:
本文实例讲述了C#中yield return用法,并且对比了使用yield return与不使用yield return的情况,以便读者更好的进行理解。具体如下:
本篇文章转载于:http://www.jb51.net/article/54810.htm
yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历。
有这样的一个int类型的集合:
需要打印出所有值大于2的元素。
不使用yield return的实现
static IEnumerable<int> FilterWithoutYield()
{
List<int> result = new List<int>();
foreach (int i in GetInitialData())
{
if (i > 2)
{
result.Add(i);
}
}
return result;
}
客户端调用:
static void Main(string[] args)
{
foreach (var item in FilterWithoutYield())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
输出结果:3,4
使用yeild return实现
static IEnumerable<int> FilterWithYield()
{
foreach (int i in GetInitialData())
{
if (i > 2)
{
yield return i;
}
}
yield break;
Console.WriteLine("这里的代码不执行");
}
客户端调用:
static void Main(string[] args)
{
foreach (var item in FilterWithYield())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
输出结果:3,4
总结:
通过单步调试发现:
虽然2种方法的输出结果是一样的,但运作过程迥然不同。第一种方法,是把结果集全部加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。
第一种方法,客户端调用过程大致为:
使用yield return,客户端调用过程大致为:
使用yield return为什么能保证每次循环遍历的时候从前一次停止的地方开始执行呢?
--因为,编译器会生成一个状态机来维护迭代器的状态。
简单地说,当希望获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就可以考虑使用yield return实现"按需供给"
本文转载于http://www.jb51.net/article/54810.htm
那么好了,理解了yield return之后,就来体验一下在u3d中是如何使用协程的吧:
StartCoroutine在unity3d的帮助中叫做协程,意思就是启动一个辅助的线程。
本篇文章转载于 http://www.cnblogs.com/xpvincent/archive/2013/07/13/3188257.html 感谢作者:马语者
在C#中直接有Thread这个线程,但是在unity中有些元素是不能操作的。这个时候可以使用协程来完成。
使用线程的好处就是不会出现界面卡死的情况,如果有一次非常大量的运算,没用线程就会出现假死的情况。
下面通过一个简单的例子来说明使用协程的好处:
上面的代码表示在GUI中定义2个label和按钮,一个按钮启动协程计算,另一个直接计算结果。由于2个方法都是计算同样的结果,计算量比较大,所以直接计算出现了暂时的卡死情况。
这个方法是协程的写法,在C#中协程要定义为IEnumerator 这个类型,javascript中不需要。
yield return 1;这句话表示返回1帧的结果。在i为100的整数时,就返回一次结果,这样可以避免大量的计算卡死。
这个方法就是直接计算结果,由于运算量比较大,所以界面会卡死,这样就可以体现出用协程的好处了。
使用IEnumerator 这个类型时,必须用yield return来返回结果,参数为数字时表示为帧数。
如yield return 1 表示每一帧返回一次结果。
本文转载于 http://www.cnblogs.com/xpvincent/archive/2013/07/13/3188257.html
以上两篇文章是我了解,学习协程的较为浅显易懂的文章。解释的很清楚。随着之后我在代码中的不断使用和尝试,有机会带来自己的心得体会。
下面贴出两篇不错的资料,供进阶阅读
http://blog.csdn.net/huang9012/article/details/38492937 http://dsqiu.iteye.com/blog/2049743
就目前理解,简单说一下自己体会啊~
1,在加载比较大的预制,资源的时候,用yield ruturn 来加载。这样避免了在游戏中某一帧加载过多资源导致卡死的情况
2,可以用协程嵌套,做计时器什么的,方便自己对对象行为的控制(详见之后)
那就把旧项目的东西拿过来,看了看源码,注意到了协程这货,而且最近同事也鼓励我们试试用协程,于是就来研究一下吧。
查了一些文档,以下是整理和总结:
本文实例讲述了C#中yield return用法,并且对比了使用yield return与不使用yield return的情况,以便读者更好的进行理解。具体如下:
本篇文章转载于:http://www.jb51.net/article/54810.htm
yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历。
有这样的一个int类型的集合:
static List<int> GetInitialData() { return new List<int>() { 1, 2, 3, 4 }; }
需要打印出所有值大于2的元素。
不使用yield return的实现
static IEnumerable<int> FilterWithoutYield()
{
List<int> result = new List<int>();
foreach (int i in GetInitialData())
{
if (i > 2)
{
result.Add(i);
}
}
return result;
}
客户端调用:
static void Main(string[] args)
{
foreach (var item in FilterWithoutYield())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
输出结果:3,4
使用yeild return实现
static IEnumerable<int> FilterWithYield()
{
foreach (int i in GetInitialData())
{
if (i > 2)
{
yield return i;
}
}
yield break;
Console.WriteLine("这里的代码不执行");
}
客户端调用:
static void Main(string[] args)
{
foreach (var item in FilterWithYield())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
输出结果:3,4
总结:
通过单步调试发现:
虽然2种方法的输出结果是一样的,但运作过程迥然不同。第一种方法,是把结果集全部加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。
第一种方法,客户端调用过程大致为:
使用yield return,客户端调用过程大致为:
使用yield return为什么能保证每次循环遍历的时候从前一次停止的地方开始执行呢?
--因为,编译器会生成一个状态机来维护迭代器的状态。
简单地说,当希望获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就可以考虑使用yield return实现"按需供给"
本文转载于http://www.jb51.net/article/54810.htm
那么好了,理解了yield return之后,就来体验一下在u3d中是如何使用协程的吧:
StartCoroutine在unity3d的帮助中叫做协程,意思就是启动一个辅助的线程。
本篇文章转载于 http://www.cnblogs.com/xpvincent/archive/2013/07/13/3188257.html 感谢作者:马语者
在C#中直接有Thread这个线程,但是在unity中有些元素是不能操作的。这个时候可以使用协程来完成。
使用线程的好处就是不会出现界面卡死的情况,如果有一次非常大量的运算,没用线程就会出现假死的情况。
下面通过一个简单的例子来说明使用协程的好处:
void OnGUI() { GUI.Label(new Rect(0, 0, 200, 50), "测试1:" + result); if (GUI.Button(new Rect(0, 100, 100, 50), "开启协程")) { StartCoroutine(GetResult()); } GUI.Label(new Rect(200, 0, 200, 50), "测试2:" + result1); if (GUI.Button(new Rect(200, 100, 100, 50), "无协程测试")) { GetResult1(); } }
上面的代码表示在GUI中定义2个label和按钮,一个按钮启动协程计算,另一个直接计算结果。由于2个方法都是计算同样的结果,计算量比较大,所以直接计算出现了暂时的卡死情况。
这个方法是协程的写法,在C#中协程要定义为IEnumerator 这个类型,javascript中不需要。
yield return 1;这句话表示返回1帧的结果。在i为100的整数时,就返回一次结果,这样可以避免大量的计算卡死。
float result; IEnumerator GetResult() { for (int i = 0; i < 1000; i++) { for (int j = 0; j < 100000; j++) { result += (i + j); } if(i%100==0) yield return 1; } }
这个方法就是直接计算结果,由于运算量比较大,所以界面会卡死,这样就可以体现出用协程的好处了。
使用IEnumerator 这个类型时,必须用yield return来返回结果,参数为数字时表示为帧数。
如yield return 1 表示每一帧返回一次结果。
本文转载于 http://www.cnblogs.com/xpvincent/archive/2013/07/13/3188257.html
以上两篇文章是我了解,学习协程的较为浅显易懂的文章。解释的很清楚。随着之后我在代码中的不断使用和尝试,有机会带来自己的心得体会。
下面贴出两篇不错的资料,供进阶阅读
http://blog.csdn.net/huang9012/article/details/38492937 http://dsqiu.iteye.com/blog/2049743
就目前理解,简单说一下自己体会啊~
1,在加载比较大的预制,资源的时候,用yield ruturn 来加载。这样避免了在游戏中某一帧加载过多资源导致卡死的情况
2,可以用协程嵌套,做计时器什么的,方便自己对对象行为的控制(详见之后)
相关文章推荐
- lua 在unity 中的协程使用
- Unity协程使用经验
- Unity如何使用WWW类和协程完成图片、视频下载播放(一)
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!
- Unity中协程的使用+自定义
- 使用 Unity Application Block(三):理解和使用依赖注入的键
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!
- Unity两点间的线性插值及其协程的使用
- 对Unity协程的深入理解
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!
- Unity中使用协程实现倒计时功能
- Unity中2D和UGUI图集的理解与使用
- 「Unity」使用协程延时执行代码
- U3D协程yield的使用和理解
- Unity 协程使用指南
- 使用 Unity Application Block(三):理解和使用依赖注入的键
- 【Unity】理解协程的原理1——实现一个自己的WaitForSeconds
- Unity 协程使用(嵌套)
- Unity中2D和UGUI图集的理解与使用
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!