Unity2D开发入门-协程

前言

在Unity中,协程(Coroutine)是一种特殊的函数,可以在程序的执行过程中暂停和恢复执行。

协程通常用于处理时间相关的任务,例如延迟执行、动画序列等。

启动协程

要在Unity中使用协程,可以按照以下步骤进行操作:

  1. 创建一个带有返回类型为IEnumerator的函数,并将其标记为协程。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    private IEnumerator MyCoroutine()
    {
    // 协程的执行逻辑
    yield return null; // 暂停执行一帧
    // 继续执行逻辑
    yield return new WaitForSeconds(2.0f); // 暂停执行2秒钟
    // 继续执行逻辑
    }
  2. 在需要启动协程的地方,使用StartCoroutine方法来启动协程。例如,在Start函数中启动协程:

    1
    2
    3
    4
    void Start()
    {
    StartCoroutine(MyCoroutine());
    }

暂停协程

在协程中使用yield语句来控制执行流程。yield return语句用于暂停执行,并在指定条件满足时恢复执行。

常用的yield语句包括:

  • yield return null;:暂停执行一帧,然后继续执行下一帧。
  • yield return new WaitForSeconds(delay);:暂停执行一段时间(以秒为单位),然后继续执行。
  • yield return new WaitForFixedUpdate();:暂停执行直到下一个固定更新帧。
  • yield return new WaitForEndOfFrame();:暂停执行直到当前帧渲染完毕。
  1. 在协程中可以使用循环、条件语句等控制流程,实现复杂的逻辑。

注意事项:

  • 协程只能在MonoBehaviour的派生类中使用。
  • 协程可以被中断和停止。可以使用StopCoroutine方法停止指定的协程,或者使用StopAllCoroutines方法停止当前对象上的所有协程。

示例

在规定时间内移动到某个位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private IEnumerator MoveObject
(
Transform objectToMove,
Vector3 endPosition,
float duration
)
{
var startTime = Time.time;
var elapsedTime = 0f;

while (elapsedTime < duration)
{
elapsedTime = Time.time - startTime;
var t = Mathf.Clamp01(elapsedTime / duration);
objectToMove.position = Vector3.Lerp
(
objectToMove.position,
endPosition,
t
);
yield return null;
}

objectToMove.position = endPosition;
}

其中

Vector3.Lerp 是 Unity 引擎中的一个函数,用于在两个向量之间进行线性插值。它的作用是在两个向量之间按照一定比例插值生成一个新的向量。

具体来说,Vector3.Lerp 的函数签名如下:

1
public static Vector3 Lerp(Vector3 a, Vector3 b, float t);

其中,参数 a 表示起始向量,参数 b 表示目标向量,参数 t 表示插值因子(取值范围为[0, 1])。

Vector3.Lerp 的返回值是一个新的向量,通过对起始向量和目标向量进行插值计算得到。

也就是返回

起点和终点练成一条线后比例从0到1中的点。

匀速向某个位置移动

起点到终点的向量

1
Vector3 direction = (endPoint - startPoint).normalized;

这样,direction 就是起点到终点的单位向量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private IEnumerator MoveObject
(
Transform objectToMove,
Vector3 endPoint,
float duration,
float mspeed
)
{
var startTime = Time.time;
var elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime = Time.time - startTime;
var startPoint = objectToMove.position;
var direction = (endPoint - startPoint).normalized;
startPoint += direction * mspeed * Time.deltaTime;
objectToMove.position = startPoint;
yield return null;
}
}

使用施加力实现

1
2
3
4
5
6
7
8
9
10
11
12
13
private IEnumerator ShootCoroutine(Rigidbody2D body, Vector2 v)
{
int frame = 0;
while (frame <= 60)
{
body.AddForce(v * speed * Time.deltaTime);
// 等待下一帧
yield return new WaitForFixedUpdate();
frame++;
}
// 继续执行后续逻辑
Destroy(body.gameObject, 1f);
}