Unity 协程 —— 很像线程,但又不是线程

协程

1. 概述

在 Unity 中,假如想做到在调用一个可能耗时很长的函数时,能够立马返回,这时候,有两种选择协程与线程。

协程可视为代码块一个一个执行,假如某一个代码块阻塞了,整个程序就会阻塞,所以理论上来说,协程还是在主线程中。而对于线程来说,即使某一段代码块阻塞,也不会导致整个程序阻塞。

但是,线程使用的时候需要十分小心,因为 UnityAPI 不是线程安全的,可能导致无法在子线程中使用 UntiyAPI,但基本数据结构还是能够使用的。因此能够用协程的,尽量使用协程。

假如你遇到高开销或长时间处理的操作时,还是可以使用线程的。例如:

  • 网络通信
  • 寻路
  • 人工智能
  • 文件操作

2. 使用说明

假如我们想在脚本 Start 时使用协程在控制台中 Debug.Log 一个信息,可以这样操作:

public class TestScript : MonoBehaviour {

    IEnumerator LogMessage(string Message)
    {
        Debug.Log(Message);
        yield return new WaitForSeconds(2.0f);
        Debug.Log("after 2 seconds");
    }

    private void Start()
    {
        StartCoroutine(LogMessage("I am king of the world"));
    }

}

效果图如下:
Unity 协程 —— 很像线程,但又不是线程_第1张图片

前言有说过,协程可理解为每次执行都只是执行一段代码,但这段代码有多长,其实是自己定义的。在代码中,有 yield return,这个很像 return 但其实不是 return 的东西。这个可以理解为代码执行到 yield return 就结束了,然后记录下这个位置,“跳出函数”。当在 Engine 进行下一次循环时,又会回到上次结束的地方,继续执行。

正常来说,返回 null 就可以了,但代码中返回的是 new WaitForSecond(2.0f),这是告诉 Engine 请 2 秒后再返回到这里,没到时间的请略过。

协程后面可以定义若干个 yield return,代表了你是如何把这堆代码拆分成一段一段。

也许有人会疑问,通过协程,“跳出函数”,那原本在函数中的临时变量还在吗?我们测试一下:

public class TestScript : MonoBehaviour {

    IEnumerator LogMessage(string Message)
    {
        int i = 1;
        Debug.Log(Message + '(' + i + ')');
        yield return null;

        i++;
        Debug.Log(Message + '(' + i + ')');

        yield return new WaitForSeconds(2.0f);
        Debug.Log("after 2 seconds");
    }

    private void Start()
    {
        StartCoroutine(LogMessage("I am king of the world"));
    }

}

效果如下:
Unity 协程 —— 很像线程,但又不是线程_第2张图片

i 即为函数的局部变量,但可以看到,i 的值并没有因 “跳出函数” 而丢失。也就是说,局部变量不会因 “跳出函数” 而丢失。想知道原理的话,可以了解一下 C# 的 yield return 的语法使用以及 Unity 如何利用该语法实现协程。

3. 常用场合

本人也是刚刚接触协程,因此并没有太多的经验。但通常看到协程出现的地方有 3 种:

  • 延迟操作,希望延迟 n 秒再执行。譬如,某个敌人死亡时,需要播放死亡动画,播放完毕才真正 Destroy 对象。
  • 大循环分段,也即是在循环多次的情况下,把每一次循环都分段下来,达到像开了线程的感觉,没有阻塞。
  • 动画效果函数化,由于协程相当于 Update 的存在,可以在协程中弄一些动画效果,譬如画面慢慢变暗效果。这样就可以把动画播放完全弄成一个函数,而不是每一次在 Update 进行下一帧的处理。

4. 结语

本人还是小白一名,有不妥当的地方请见谅。

学习是一个漫长的过程。在探索中不断发现新知识是你一直前进的动力。o( ̄▽ ̄)ブ
Unity 协程 —— 很像线程,但又不是线程_第3张图片

你可能感兴趣的:(Unity,游戏)