协同程序

    实际情况是,函数 Fade 不会实现你期望的效果。为了使渐变过程可见,alpha 必须随着桢序列降低,以渲染显示中间值。但是,该函数将在一帧内完整地执行。你将永远不会看到中间值,对象会立即消失。

    可以把代码添加到 Update 函数中,逐桢地执行淡出,来处理这种情况。不过,更方便的方式是使用协程(协同程序)执行这种任务。

    协程就像一个函数,它能够暂停执行并将控制权返回给 Unity,但是在下一桢时,可以在暂停的位置继续执行。在 C# 中,可以像这样声明协程:

    1. IEnumerator Fade() {
    2. for (float f = 1f; f >= 0; f -= 0.1f) {
    3. Color c = renderer.material.color;
    4. c.a = f;
    5. renderer.material.color = c;
    6. yield return null;
    7. }
    8. }
    1. void Update() {
    2. if (Input.GetKeyDown("f")) {
    3. StartCoroutine("Fade");
    4. }

    在 UnityScript 中,事情稍微简单一些。任何含有 yield 语句的函数都被认为是一个协程,不需要显示声明返回类型 IEnumerator:

    此外,在 UnityScript 中,可以通过直接调用协程来启动它,就像它是一个普通的函数一样:

    1. if (Input.GetKeyDown("f")) {
    2. Fade();
    3. }
    4. }

    你将会注意到,在协程的生命周期内,Fade 函数中的循环计数器一直保持正确的值。实际上,yield 之间的任何变量或属性都将正确地保留。

    1. IEnumerator Fade() {
    2. for (float f = 1f; f >= 0; f -= 0.1f) {
    3. Color c = renderer.material.color;
    4. c.a = f;
    5. renderer.material.color = c;
    6. yield return new WaitForSeconds(.1f);
    7. }

    在 UnityScript 中:

    协程可以把某些效果分散在一段时间内,也可以有效地优化性能。游戏中的许多任务需要定期执行,最明显的方式是将它们包含在 Update 函数中执行。但是 Update 函数通常每秒调用多次。当任务不需要如此频繁地重复时,你可以把它放入协程定期更新,而不是每桢都更新。一个例子是在敌人靠近玩家时触发警告。代码看起来可能像这样:

    1. function ProximityCheck() {
    2. if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
    3. return true;
    4. }
    5. }
    6. return false;
    7. }

    如果有很多敌人,每桢都调用该函数可能会带来很大的开销。不过,你可以使用协程每秒调用该函数 10 次:

    1. IEnumerator DoCheck() {
    2. for(;;) {
    3. ProximityCheck;
    4. yield return new WaitForSeconds(.1f);
    5. }