在Unity中有多种等待方式。以下是我认为值得介绍的方法:
1. 用协程和WaitForSeconds:
这是迄今为止最简单的方法。将所有需要等待一段时间的代码放入协程函数中,然后使用WaitForSeconds
进行等待。注意,在协程函数中,你可以使用StartCoroutine(yourFunction)
调用该函数。
下面的例子是先旋转90度,然后等待4秒,旋转40度,然后等待2秒,最后再旋转20度。
void Start()
{
StartCoroutine(waiter());
}
IEnumerator waiter()
{
//Rotate 90 deg
transform.Rotate(new Vector3(90, 0, 0), Space.World);
//Wait for 4 seconds
yield return new WaitForSeconds(4);
//Rotate 40 deg
transform.Rotate(new Vector3(40, 0, 0), Space.World);
//Wait for 2 seconds
yield return new WaitForSeconds(2);
//Rotate 20 deg
transform.Rotate(new Vector3(20, 0, 0), Space.World);
}
2. 用协程和WaitForSecondsRealtime:
WaitForSeconds
和WaitForSecondsRealtime
之间的唯一区别是WaitForSecondsRealtime
使用未标度的时间等待,这意味着当使用Time.timeScale
暂停游戏时,WaitForSecondsRealtime
函数不会受到影响,但WaitForSeconds
会受到影响
void Start()
{
StartCoroutine(waiter());
}
IEnumerator waiter()
{
//Rotate 90 deg
transform.Rotate(new Vector3(90, 0, 0), Space.World);
//Wait for 4 seconds
yield return new WaitForSecondsRealtime(4);
//Rotate 40 deg
transform.Rotate(new Vector3(40, 0, 0), Space.World);
//Wait for 2 seconds
yield return new WaitForSecondsRealtime(2);
//Rotate 20 deg
transform.Rotate(new Vector3(20, 0, 0), Space.World);
}
3. 使用协程,并且每一帧用Time.deltaTime递增一个变量:
一个很好的例子是,当你需要在屏幕上显示它已经等待了多少时间,它就像一个计时器。
当你想用一个boolean
来中断等待/睡眠时,它也可以完成。
bool quit = false;
void Start()
{
StartCoroutine(waiter());
}
IEnumerator waiter()
{
float counter = 0;
//Rotate 90 deg
transform.Rotate(new Vector3(90, 0, 0), Space.World);
//Wait for 4 seconds
float waitTime = 4;
while (counter < waitTime)
{
//Increment Timer until counter >= waitTime
counter += Time.deltaTime;
Debug.Log("We have waited for: " + counter + " seconds");
//Wait for a frame so that Unity doesn't freeze
//Check if we want to quit this function
if (quit)
{
//Quit function
yield break;
}
yield return null;
}
//Rotate 40 deg
transform.Rotate(new Vector3(40, 0, 0), Space.World);
//Wait for 2 seconds
waitTime = 2;
//Reset counter
counter = 0;
while (counter < waitTime)
{
//Increment Timer until counter >= waitTime
counter += Time.deltaTime;
Debug.Log("We have waited for: " + counter + " seconds");
//Check if we want to quit this function
if (quit)
{
//Quit function
yield break;
}
//Wait for a frame so that Unity doesn't freeze
yield return null;
}
//Rotate 20 deg
transform.Rotate(new Vector3(20, 0, 0), Space.World);
}
你仍然可以通过将while
循环移动到另一个协程函数来简化这个过程,并且仍然能够看到它在计数,甚至可以中断计数器。
bool quit = false;
void Start()
{
StartCoroutine(waiter());
}
IEnumerator waiter()
{
//Rotate 90 deg
transform.Rotate(new Vector3(90, 0, 0), Space.World);
//Wait for 4 seconds
float waitTime = 4;
yield return wait(waitTime);
//Rotate 40 deg
transform.Rotate(new Vector3(40, 0, 0), Space.World);
//Wait for 2 seconds
waitTime = 2;
yield return wait(waitTime);
//Rotate 20 deg
transform.Rotate(new Vector3(20, 0, 0), Space.World);
}
IEnumerator wait(float waitTime)
{
float counter = 0;
while (counter < waitTime)
{
//Increment Timer until counter >= waitTime
counter += Time.deltaTime;
Debug.Log("We have waited for: " + counter + " seconds");
if (quit)
{
//Quit function
yield break;
}
//Wait for a frame so that Unity doesn't freeze
yield return null;
}
}
等待/睡眠,直到变量更改或等于另一个值。
4. 使用协程和WaitUntil函数:
等待一个条件变为true
。例如,一个函数会等待玩家的分数达到100,然后加载下一个关卡。
float playerScore = 0;
int nextScene = 0;
void Start()
{
StartCoroutine(sceneLoader());
}
IEnumerator sceneLoader()
{
Debug.Log("Waiting for Player score to be >=100 ");
yield return new WaitUntil(() => playerScore >= 10);
Debug.Log("Player score is >=100. Loading next Leve");
//Increment and Load next scene
nextScene++;
SceneManager.LoadScene(nextScene);
}
5. 使用协程和WaitWhile函数:
等待一个条件变为true
。 一个示例是当你按退出键时想退出应用程序。
void Start()
{
StartCoroutine(inputWaiter());
}
IEnumerator inputWaiter()
{
Debug.Log("Waiting for the Exit button to be pressed");
yield return new WaitWhile(() => !Input.GetKeyDown(KeyCode.Escape));
Debug.Log("Exit button has been pressed. Leaving Application");
//Exit program
Quit();
}
void Quit()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
6. 使用Invoke函数:
在调用Invoke
函数时,可以将调用该函数之前的等待时间传递给它的第二个参数。
下面的示例将在调用Invok
e 5秒钟后调用feedDog()
函数。
void Start()
{
Invoke("feedDog", 5);
Debug.Log("Will feed dog after 5 seconds");
}
void feedDog()
{
Debug.Log("Now feeding Dog");
}
7. 使用Update()函数和Time.deltaTime:
它就像#3一样,只是它不使用协程,它使用了Update函数。
这个方法的问题在于它需要太多的变量,因此它不会每次都运行,而是在计时器结束时运行一次。
float timer = 0;
bool timerReached = false;
void Update()
{
if (!timerReached)
timer += Time.deltaTime;
if (!timerReached && timer > 5)
{
Debug.Log("Done waiting");
feedDog();
//Set to false so that We don't run this again
timerReached = true;
}
}
void feedDog()
{
Debug.Log("Now feeding Dog");
}
在Unity中还有其他等待的方法,但你一定要知道上面提到的那些方法,因为这可以让你更容易地在Unity中制作游戏。在什么情况下使用某一个方法都要视情况而定。