unity中的协程

作者 Claymore 日期 2016-06-10
unity中的协程

协程

协程并非真正的多线程。协程其实是等某个操作完成之后再执行后面的代码,或者说是控制代码在特定的时机执行。协程只是部分执行,并假定在适当的条件得到满足,在未来的某一时刻将被恢复,直到它的工作完成。
或者说,协同程序,在主程序运时开启另一段逻辑处理,协同当前程序的执行。而多线程在Unity渲染和复杂逻辑运算时可以高效的使用多核CPU,帮助程序可以更高效的运行。

先看一个示例,点击按钮让cube旋转30°,过三秒后再旋转30°

代码:

using UnityEngine;
using System.Collections;

public class IEnumeratorTest : MonoBehaviour {
    public void BtnClick()
    {
        StartCoroutine(Test());
    }

    IEnumerator Test()
    {
        this.transform.Rotate(Vector3.up * 30);
        yield return new WaitForSeconds(3); //等待三秒
        this.transform.Rotate(Vector3.forward * 30);
    }
}
  • 协程不会阻塞主线程
  • 协程在游戏中用于AI,降低它的资源利用,不让它总是每帧检测,而是像上面等几秒检测一次。

调用函数

调用函数是协程的简化写法,分为:

  • Invoke 调用函数: 隔多长时间执行一次某方法。

    public void Invoke(string methodName,float time);
    
  • InvokeRepeating 重复调用函数: 指定时间、指定间隔时间重复调用。

    public void InvokeRepeating(string methodName, float time, float repeatRate)
    

    eg:

    void Start () {
    
        Invoke("test", 5f);   //5秒后调用一次text
    
        InvokeRepeating("test1", 1f, 1f);  //重复调用,1s时开始,1s间隔重复调用。
    }
    
    void test()
    {
        Debug.Log("this is test");
    }
    
    void test1()
    {
        Debug.Log("this is test1");
    }
    

协程和调用函数的区别

  • 调用函数是协程的简化写法。
  • 调用函数语法简单,但是不灵活,协程注重“非固定时间间隔”。

多线程

Unity3D编程时,总有个主线程执行你的代码,也可以创建额外的线程和主线程同时运行。而Unity中,你仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用。任何企图访问这些项目的第二个线程都将失败并引发错误,这是一个要重视的一个限制。

先记住一句结论:
分线程可以做 基本类型的计算, 以及非Unity(包括.Net及SDK)的API
使用多线程注意:

  • 变量都是共享的(都能指向相同的内存地址)
  • UnityEngine的API不能在分线程运行
  • UnityEngine定义的基本结构(int,float,Struct定义的数据类型)可以在分线程计算,如 Vector3(Struct)可以 , 但Texture2d(class,根父类为Object)不可以。
  • UnityEngine定义的基本类型的函数可以在分线程运行
  • tread类等多线程一般不用于unity里,它会和 unity的api起冲突,一般socket类用多线程。

Loom

Unity的函数执行机制是帧序列调用,甚至连Unity的协程Coroutine的执行机制都是确定的,如果可以使用多线程访问UnityEngine的对象和api就得考虑同步问题了,也就是说Unity其实根本没有多线程的机制,协程只是达到一个延时或者是当指定条件满足是才继续执行的机制。这时我们发现了Loom.
我们只需要关系两个函数:RunAsync(Action)和QueueOnMainThread(Action, [optional] float time) 就可以轻松实现一个函数的两段代码在C#线程和Unity的主线程中交叉运行。原理也很简单:用线程池去运行RunAsync(Action)的函数,在Update中运行QueueOnMainThread(Acition, [optional] float time)传入的函数。
更多请看,点击这里