协同程序

首先,必须要了解的是,游戏引擎(例如 Unity)在基于框架的范例上工作。

代码在每一帧中执行。

这包括 Unity 自己的代码和代码。

在考虑框架时,重要的是要了解框架何时发生绝对不能保证。它们不会发生在常规节拍上。帧之间的间隙可以是例如 0.02632 然后 0.021167 然后是 0.029778,依此类推。在这个例子中,它们都是1/50 秒,但它们都是不同的。而且在任何时候,你可能会得到一个花费更长或更短的框架; 并且你的代码可以在框架内的任何时间执行。

考虑到这一点,你可能会问:在 Unity 中如何访问代码中的这些帧?

很简单,你使用 Update() 调用,或者使用协程。 (确实 - 它们完全相同:它们允许每帧运行代码。)

协程的目的是:

你可以运行一些代码,然后停止并等待直到将来的某个框架

你可以等到下一帧,你可以等待多个帧,或者你可以在将来等待几秒钟的大致时间。

例如,你可以等待大约一秒钟,这意味着它将等待大约一秒钟,然后将代码放在大约一秒钟的某个帧中。 (事实上​​,在该框架内,代码可以随时运行。)重复:它不会是一秒钟。准确的计时在游戏引擎中毫无意义。

在协程内:

要等一帧:

// do something
yield return null;  // wait until next frame
// do something

等待三帧:

// do something
yield return null;  // wait until three frames from now
yield return null;
yield return null;
// do something

等待大约半秒钟:

// do something
yield return new WaitForSeconds (0.5f); // wait for a frame in about .5 seconds
// do something

每一帧做一些事情:

while (true)
{
    // do something
    yield return null;  // wait until the next frame
}

这个例子与简单地在 Unity 的更新调用中放置一些内容完全相同:执行某些操作的代码每帧运行一次。

将 Ticker 附加到 GameObject。当该游戏对象处于活动状态时,勾选将会运行。请注意,当游戏对象变为非活动状态时,脚本会小心地停止协程; 这通常是正确设计协同程序使用的一个重要方面。

using UnityEngine;
using System.Collections;

public class Ticker:MonoBehaviour {

    void OnEnable()
    {
        StartCoroutine(TickEverySecond());
    }

    void OnDisable()
    {
        StopAllCoroutines();
    }

    IEnumerator TickEverySecond()
    {
        var wait = new WaitForSeconds(1f); // REMEMBER: IT IS ONLY APPROXIMATE
        while(true)
        {
            Debug.Log("Tick");
            yield return wait;  // wait for a frame, about 1 second from now
        }
    }
}