协程中的循环
本课属于 Coddy Unity 学习旅程的“物理与游戏玩法”单元。第 25 课,共 71 课。
包含 yield return 的循环会跨越许多帧运行,因为每次循环都会暂停,然后才进入下一次循环。使用 WaitForSeconds,循环就会按节拍重复执行某些操作。这个警报灯会闪烁 3 次:
IEnumerator Flash()
{
for (int i = 0; i < 3; i++)
{
lamp.enabled = true;
yield return new WaitForSeconds(0.2f);
lamp.enabled = false;
yield return new WaitForSeconds(0.2f);
}
}使用 yield return null 时,循环会在每一帧执行一点操作,直到满足条件。这就是协程为某个对象制作动画的方式。这个气球的初始缩放值为 1,它会以每秒 0.5 的速度膨胀,直到缩放值达到 2,然后输出:
IEnumerator Inflate()
{
while (transform.localScale.x < 2f)
{
transform.localScale += Vector3.one * 0.5f * Time.deltaTime;
yield return null;
}
Debug.Log("Full");
}Time.deltaTime 在这里的作用和 Update() 中一样:协程每帧恢复一次,而循环结束后才会执行循环后面的那一行。没有 yield 的话,整个循环会在一帧内运行完,气球会立刻膨胀完成。只要每次循环都会让出执行权,协程中的 while (true) 循环就没有问题;如果不让出执行权,它就永远不会把这一帧交还给 Unity,Unity 编辑器就会冻结。
挑战
简单编写 Ride,让吊闸完成一次完整行程。
- 设置
Vector3 up = down + Vector3.up * height;。当while (transform.position != up)时,使用Vector3.MoveTowards(transform.position, up, speed * Time.deltaTime)移动,并执行yield return null;。 - 记录
Open,然后执行yield return new WaitForSeconds(1f);。 - 用相同的方式循环移动回
down,然后记录Closed。
按下 开始,再按 Space:闸门升起、等待,然后关闭。接着点击 检查。
亲手试试
using System.Collections;
using UnityEngine;
public class Portcullis : MonoBehaviour
{
public float speed = 1.5f;
public float height = 3f;
Vector3 down;
void Start()
{
down = transform.position;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(Ride());
}
}
IEnumerator Ride()
{
// 以 speed 的速度上升 height 个单位,并记录 Open;停留 1 秒后下降,再记录 Closed
yield return null;
}
}
物理与游戏玩法中的所有课
自己练习: Unity 在线编辑器