协同的作用:
1.延时(等待)一段时间执行代码
2.等待某个操作结束之后再执行代码
这里需要记住:协同不是县城。也不是异步执行的。他本身和Update函数是一样的在主线程执行的 就是一个可以主动添加和移除的Update方案,而且他还可以挂起。(这里就要说到Loading界面的LoadLevelAsync异步加载了。他也是个协同)
大部分的文章都说Unity在每一帧(Frame)都会去处理对象上的协程。Unity主要是在Update后去处理协程(检查协程的条件是否满足)。然后我实践了下发现这句话很容易让人误解(尼玛我一开始就理解错误了,希望大家不要和我有一样的错误)。
下面是开启一个协同看Log语句的例子
<pre name="code" class="csharp"><span style="font-family:KaiTi_GB2312;font-size:18px;">using UnityEngine;
using System.Collections;
public class Test1 : MonoBehaviour {
public int m_Count;
private bool m_Flag = false;
// Use this for initialization
void Start () {
StartCoroutine(FunctionA());
}
void FixedUpdate()
{
if (m_Flag)
{
m_Count++;
Debug.LogError("FixedUpdate:" + m_Count);
}
}
// Update is called once per frame
void Update () {
if (m_Flag)
{
m_Count++;
Debug.LogError("Update:" + m_Count);
}
}
void LateUpdate()
{
if (m_Flag)
{
m_Count++;
Debug.LogError("LateUpdate:" + m_Count);
}
}
private IEnumerator FunctionA()
{
Debug.LogError("m_Count:" + m_Count);
m_Flag = true;
yield return null;
Debug.LogError("m_Count:" + m_Count);
}
}
</span>
Log:
很明显看到执行的顺序是一旦调用协同函数就会在Update之前进入协同代码里面。直到遇到yield return null 挂起之后,等待下一帧的Update结束之后再访问挂起地方的代码。 所以协同的执行顺序是 1.调用协同函数-->2.直接进入协同函数内部执行代码---->3.执行到yield return null挂起 ----->4.执行Update-->5.执行LastUpdate--->6.执行下一帧的Update----->7.执行协同内部挂起部分代码的后续部分。(这里普遍的写法是在协同方法里的第一代码是就挂起 yield return null)。
上面可以很清晰的看到协同是每一帧的Update之后会去轮训查看的(注意是挂起之后的下一帧)。
项目中遇到的问题:
在项目中时常要遇到这样一个需求:战斗结束结算经验增加,数值跳转从0-100。这时候就需要用到协同操作。
之前写过这样的代码:本意是想让他每0.01秒+1,1秒就可以加到100了。实际效果却达不到
//错误
IEnumerable AddExp()
{
yield return null;
int tmpExp = 0;
if (tmpExp<MaxExp)
{
tmpExp++;
yield return new WaitForSeconds(0.01f);
}
}
理由:本身协同也是属于和Update类似。如果你的游戏帧数强制定死30FPS,那么在1秒钟的时间协同最多只能执行30次。即使你 yield return new WaitForSeconds(0.01f);等待0.01秒。实际效果就是他等待的时间会超过0.01秒。 1分钟之内Exp最多只能添加30.通过这个错误的案例能更深刻的了解协同