Unity3D 协程管理

作者: 雨落随风 | 来源:发表于2017-08-06 02:33 被阅读643次

Unity里面的协程好用,但总是在如何关闭指定协程,尤其是关闭带参数的协程的问题上困惑不已。
在本文,笔者带你用最简单的方式(2个方案)管理这些运行中的协程,做到点对点关闭,即便是带参数协程,也能点对点关闭。

思路:

字典保存协程引用(或者运行中的协程的引用),需要关闭指定的协程,只需拿到这个协程引用然后使用StopCoroutineAPI即可,下面我们码代码试试这个思路的可行性(附动画)。

代码:

方案一,执行StartCoroutine,将返回这个协同程序的引用,将这个引用存到字典,需要的时候直接StopCoroutine(这个引用);

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestIEnumlator01 : MonoBehaviour {
    //方案一,执行StartCoroutine,将返回这个协同程序的引用,需要的时候直接StopCoroutine(这个引用);
    Dictionary<string, Coroutine> CoroutineDic = new Dictionary<string, Coroutine>();
      //消息输出字典,用于Debug
    Dictionary<string, string> MessageDic = new Dictionary<string, string>() {
        { "a", "Test04" },
        { "s", "Test05" },
        { "d", "Test06" }
    };
    void Start () {
        //模拟运行协程
        CoroutineDic.Add("a", StartCoroutine(Test04()));
        CoroutineDic.Add("s", StartCoroutine(Test05(1f)));
        CoroutineDic.Add("d", StartCoroutine(Test06("测试", 1f)));
    }

    private void Update()
    {
        if (Input.anyKeyDown)
        {
            string name = Input.inputString;
            if (CoroutineDic.ContainsKey(name))
            {
                StopCoroutine(CoroutineDic[name]);
                CoroutineDic.Remove(name);
                Debug.Log(string.Format("我按下了{0}键,字典还有{1}个对象,注意看协程{2}还有输出不?", name, CoroutineDic.Count, MessageDic[name]));
            }
        }
    }
    //以下协程均为测试用,为了便于观察,均为死循环且定时均为1秒
    IEnumerator Test04()//不带参数协程
    {
        while (true)
        {
            yield return new WaitForSeconds(1f);
            Debug.Log("我是Test04:"+Time.realtimeSinceStartup);
        }
    }
    IEnumerator Test05(float _DelayTime)//带一个参数的协程
    {
        while (true)
        {
            yield return new WaitForSeconds(_DelayTime);
            Debug.Log("我是Test05:" + Time.realtimeSinceStartup);
        }
    }
    IEnumerator Test06(string msg,float delayTime)//带两个参数的协程
    {
        while (true)
        {
            yield return new WaitForSeconds(delayTime);
            Debug.Log("我是Test06:"+ Time.realtimeSinceStartup + "传入字符串为:" + msg);
        }
    }
}

方案二,将协程方法名的引用先添加到字典,然后查找指定协程方法名的引用,用这个引用就可以随意开启关闭了;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestIEnumlator02 : MonoBehaviour {
    //方案二,将协程方法名的引用先添加到字典,然后查找指定协程方法名的引用,用这个引用就可以随意开启关闭了;
    Dictionary<string, IEnumerator> IEnumeratorDic = new Dictionary<string, IEnumerator>();
    //消息输出字典,用于Debug
    Dictionary<string, string> MessageDic = new Dictionary<string, string>() {
        { "q", "Test01" },
        { "w", "Test02" },
        { "e", "Test03" }
    };
    void Start () {
        //添加协程引用,并为其配置一个键,方便后续操作
        IEnumeratorDic.Add("q",Test01());
        IEnumeratorDic.Add("w",Test02(1f));
        IEnumeratorDic.Add("e",Test03("测试",1f));
        //模拟执行这些协程
        foreach (var item in IEnumeratorDic)
        {
            StartCoroutine(item.Value);
        }
    }

    private void Update()
    {
        if (Input.anyKeyDown)
        {
            string name=Input.inputString;
            if (IEnumeratorDic.ContainsKey(name))
            {
                StopCoroutine(IEnumeratorDic[name]);
                IEnumeratorDic.Remove(name);
                Debug.Log(string.Format("我按下了{0}键,字典还有{1}个对象,注意看协程{2}还有输出不?", name, IEnumeratorDic.Count,MessageDic[name]));
            }
        }
    }

    //以下协程均为测试用,为了便于观察,均为死循环且定时均为1秒
    IEnumerator Test01()//不带参数协程
    {
        while (true)
        {
            yield return new WaitForSeconds(1f);
            Debug.Log("我是Test01:" + Time.realtimeSinceStartup);
        }
    }
    IEnumerator Test02(float _DelayTime)//带一个参数的协程
    {
        while (true)
        {
            yield return new WaitForSeconds(_DelayTime);
            Debug.Log("我是Test02:" + Time.realtimeSinceStartup);
        }
    }
    IEnumerator Test03(string msg, float delayTime)//带两个参数的协程
    {
        while (true)
        {
            yield return new WaitForSeconds(delayTime);
            Debug.Log("我是Test03:" + Time.realtimeSinceStartup + "传入字符串为:" + msg);
        }
    }
}

动画:

效果演示

总结:

原来,协程也可以这么好用的,想执行谁,想停止谁,不管你带没带参数,都可以单独停止,单独启动。
想想,以前为了关闭一个带参数的协程,不得不执行 StopAllCoroutines()也是醉了;
如果结合字典,把这些协程与key对应起来,那取用起来不就更方便啦!

小知识:

1、如果一个类里面协程有多个重载,且均只有一个参数,可以用如下的API启动。

StartCoroutine("FuncName",1);
StartCoroutine("FuncName","参数");
StartCoroutine("FuncName",gameObject);

2、像tips1那样使用字符串来开启协程,有一个好处:就是使用StopCoroutine("FuncName")能够停止所有的运行在这个实例上的有着这个方法名的协程。

3、相应的,用StartCoroutine(FuncName(1))这样开启的协程,不管有无参数,StopCoroutine("FuncName")都是不凑效的。
4、将Coroutine所在的脚本设为enable = false并不能够将Coroutine停止,因为它跟Monobehavior是同层级的。

标签:unity 3d,IEnumerator 协程,StartCoroutine,StopCoroutine关闭协程,关闭指定协程,关闭指定的带参数协程

相关文章

  • Unity3D 协程管理

    Unity里面的协程好用,但总是在如何关闭指定协程,尤其是关闭带参数的协程的问题上困惑不已。在本文,笔者带你用最简...

  • Kotlin协程(4)✔️管理协程

    等待协程结束超时设置取消协程   协程的管理比线程的管理要简单的多。 等待协程结束   前面提到过 join 函数...

  • Unity StartCoroutine

    一、【Unity3D】协程Coroutine的运用[https://blog.csdn.net/yongh701/...

  • [Unity3D] 协程管理CoroutineManager

    很多时候协程在Unity中扮演了非常关键角色。在本文,笔者将带大家整合一个协程管理工具,常言道:好马配好鞍嘛~ 写...

  • 协程

    协程 1. 协程介绍 协程又称微线程,从名字可以看出,协程的粒度比线程更小,并且是用户管理和控制的,多个协程可以运...

  • Unity3D协程

    voidStart() { Debug.Log("1"); StartCoroutine(Do()); Deb...

  • Unity3D笔记

    Unity3D内置的回调消息,如Start,是可以写成返回IEnumerator的签名。 这段代码确实可以像协程那...

  • kotlin 协程之Job对象

    对于一个创建的协程(通过launch或者async),会返回一个Job实例,该实例是协程的唯一标示,并且负责管理协...

  • python异步协程(aiohttp,asyncio)

    python异步协程 环境:python3.7.0 协程 协程,英文叫做 Coroutine,又称微线程,纤程,协...

  • 协程(三)IEnumerable、IEnumerator、for

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

网友评论

本文标题:Unity3D 协程管理

本文链接:https://www.haomeiwen.com/subject/fmowlxtx.html