zoukankan      html  css  js  c++  java
  • Unity3D协程的简单使用

      由于Unity 3D是单线程的,因此要想实现一些类似于多线程的功能,Unity实现了协程机制,要明确协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。
      协程的定义
    IEnumerator test1(float waitTime) {//可变参数
        yield return null;//yield return表示协程暂停,将控制权交给Unity3D
    }
      开启协程
    public Coroutine StartCoroutine(IEnumerator routine);
    public Coroutine StartCoroutine(string methodName, [DefaultValue("null")] object value);
      停止协程
    public void StopCoroutine(string methodName);
    public void StopCoroutine(IEnumerator routine);
    //前者是使用方法名字符串,后者是使用方法的引用。
    //前者可以停止第一个名字为methodName的协程;后者可以准确地停止你引用的那个协程
    //第一种
    StartCoroutine("DoSomething");
    yield return new WaitForSeconds(2f);
    StopCoroutine("DoSomething");
    
    //第二种
    IEnumerator dosomething = DoSomething();
    StartCoroutine(dosomething);
    yield return new WaitForSeconds(2f);
    StopCoroutine(dosomething);
    
    //错误示例:并不能停止DoSomething,开启的协程和停止的协程不是同一个引用
    StartCoroutine(DoSomething());
    yield return new WaitForSeconds(2f);
    StopCoroutine(DoSomething());

      延时功能

    IEnumerator test2(float waitTime) {
        //等待waitTime秒之后执行后续代码
        yield return new WaitForSeconds(waitTime);
        //暂停协程直到下一次FixedUpdate时才会继续执行协程,WaitForFixedUpdate类暂停的时间取决于Unity3D的编辑器中的
        TimeManager的FixedTimestep中的值
        yield return new WaitForFixedUpdate();
        //等到所有摄像机和GUI被渲染完成后,再恢复协程的执行
        yield return new WaitForEndOfFrame();
    }
      使用WaitForEndOfFrame()延时截取当前屏幕的画面
    IEnumerator ScreenShotPNG() {
        yield return new WaitForEndOfFrame();
        int width = Screen.width;
        int height = Screen.height;
        Texture2D tex = new Texture2D(width,height,TextureFormat.RGB24,false);
        tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        tex.Apply();
        byte[] bytes = tex.EncodeToPNG();
        Destroy(tex);
        File.WriteAllBytes(Application.dataPath + "/../SaveScreen.png", bytes);
    }
    协程背后的迭代器原理
    C#代码:
    void Main(){
        IEnumerable<int> enumerable = TestStateChange();
        IEnumerator enumerator = enumerable.GetEnumerator();//此时迭代器状态由-2变为0
        bool hasNext = enumerator.MoveNext();//迭代器开始Running,迭代器状态由0变为-1
        Console.WriteLine("第一次调用MoveNext, 是否有数据" + hasNext); 
        hasNext = enumerator.MoveNext();
        Console.WriteLine("第二次调用MoveNext, 是否有数据" + hasNext);
        hasNext = enumerator.MoveNext();
        Console.WriteLine("第三次调用MoveNext, 是否有数据" + hasNext);
    }
    
    IEnumerable<int> TestStateChange() {
        Console.WriteLine("----我TestStateChange是第一行代码");
        Console.WriteLine("----我是第一个yield return前的代码");
        yield return 1;
        Console.WriteLine("----我是第一个yield return后的代码");
        Console.WriteLine("----我是第二个yield return前的代码");
        yield return 2;
        Console.WriteLine("----我是第二个yield return后的代码");
    }
    迭代器内部状态机的状态切换。
    -2状态:只有IEnumerable才有,表明在第一次调用GetEnumerator之前的状态
    -1状态:C#语言标准中规定的Running状态,表明此迭代器正在执行,当然,也会用于After状态
    0状态:Before状态,表明MoveNext()还一次都没有调用过
     
    WWW和协程
    public class HttpWrapper : MonoBehaviour {
        public void GET(string url, Action<WWW> onSuccess, Action<WWW> onFail = null) {
            WWW www = new WWW(url);
            StartCoroutine(WaitForResponse(www, onSuccess, onFail));
        }
    
        public void POST(string url, Dictionary<string, string> post, Action<WWW> onSuccess, Action<WWW> onFail = null)
        {
            WWWForm form = new WWWForm();
            foreach (KeyValuePair<string, string> arg in post)
            {
                form.AddField(arg.Key, arg.Value);
            }
            WWW www = new WWW(url, form);
            StartCoroutine(WaitForResponse(www, onSuccess, onFail));
        }
        IEnumerator WaitForResponse(WWW www, Action<WWW> onSuccess, Action<WWW> onFail = null) {
            yield return www;
            if (www.error == null)
            {
                onSuccess(www);
            }
            else {
                if (onFail != null) {
                    onFail(www);
                }
            }
        }
    }
  • 相关阅读:
    洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk( 普及-)
    洛谷 P1909 [NOIP2016 普及组] 买铅笔
    全排列问题
    集合的划分(setsub)
    自然数拆分-回溯
    洛谷 P4414 [COCI2006-2007#2] ABC
    洛谷 P5709 【深基2.习6】Apples Prologue
    洛谷 P4326 [COCI2006-2007#1] Herman
    平面分割
    洛谷 P1601 A+B Problem(高精)
  • 原文地址:https://www.cnblogs.com/tqw1215/p/13388703.html
Copyright © 2011-2022 走看看