今天,换项目组以后,不用lable,想用下自己定制的数字,发现居然没人写。
那就把旧项目的东西拿过来,看了看源码,注意到了协程这货,而且最近同事也鼓励我们试试用协程,于是就来研究一下吧。
查了一些文档,以下是整理和总结:
本文实例讲述了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,可以用协程嵌套,做计时器什么的,方便自己对对象行为的控制(详见之后)