Unity3D Coroutine携程管理器

Unity3D Coroutine携程管理器

  • 个人需求
  • 使用效果
  • 思路原理
  • 代码实现
  • 未来优化

在Unity3D的编程中携程一直占据很重要的位置,上到场景加载下到值渐变都有携程的参与.
但是目前网上对于携程的管理并没有较好的解决方案,所以个人实现了一套携程管理机制

个人需求

实现携程管理器,对携程的创建销毁进行全局管理.

使用效果

使用范例:

public class TestScript : MonoBehaviour,ISingleCoroutine
{
    private void Awake()
    {
        this.StartSingleCoroutine(1, Tick1(1));
        this.StartSingleCoroutine(2, Tick1(2));
        this.StartSingleCoroutine(2, Tick1(3));

        this.StartSingleCoroutine(3, Tick2());
        this.StopSingleCoroutine(3);
    }
    private void OnDestroy()
    {
        this.StopAllSingleCoroutines();
    }
    IEnumerator Tick1(int i)
    {
        for (; ; )
        {
            Debug.Log("Howdy"+i);
            yield return null;
        }
    }
    IEnumerator Tick2()
    {
        for (; ; )
        {
            Debug.Log("Hello Thereeeee");
            yield return null;
        }
    }
}

效果:
Unity3D Coroutine携程管理器_第1张图片

思路原理

个人理解的携程机制:
Update内遍历,满足条件则执行.

携程的创建与销毁:
创建:StartCoroutine重载,会返回Coroutine以供管理 只使用参数为IEnumerator的重载 否则会造成较高开销.
销毁:StopCoroutine重载,使用参数为Coroutine的重载达到针对单个携程的管理.

范例:

public class TestScript : MonoBehaviour
{
    private void Awake()
    {
        Coroutine cor_temp;		//缓存
        cor_temp = StartCoroutine(IETemp());		//创建
        StopCoroutine(cor_temp);		//销毁
    }

    IEnumerator IETemp()
    {
        for (; ; )
        {
            Debug.Log("Howdy");
            yield return null;
        }
    }
}

所以对创建产生的Coroutine进行管理即可实现需求

代码实现

思路:
1.将所有携程集中到一个Monobehaviour单例中管理
2.需要使用携程的脚本继承接口并分配接口ID
3.通过接口从元函数创建与销毁携程

:
SingleTonMono 为个人使用的Mono单例模板类,初始化时创建实例

管理器单例:

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

public interface ISingleCoroutine //定义接口
{
}
class CoroutineManager : SingletonMono<CoroutineManager>	//管理器单例 调用时创建 
{
    internal static List<ISingleCoroutine> L_Target = new List<ISingleCoroutine>();
    internal static Dictionary<int, Coroutine> Dic_Coroutines = new Dictionary<int, Coroutine>();
    Dictionary<int, Coroutine> CoroutineDic = new Dictionary<int, Coroutine>();
    internal static void QuestForRange(ISingleCoroutine target, ref int min, ref int max)	//接口请求携程ID范围
    {
        min = L_Target.FindIndex(p => p == target) * 1000;
        max = min + 999;
    }
    internal static int QuestForIndex(ISingleCoroutine target, int index)		//携程请求ID
    {
        int targetIndex = 0;
        if (!L_Target.Contains(target))
            L_Target.Add(target);

        targetIndex += L_Target.FindIndex(p => p == target) * 1000;
        targetIndex += index;
        return targetIndex;
    }
}

接口从元函数:

public static class ISingleCoroutine_Extend
{
    public static void StartSingleCoroutine(this ISingleCoroutine target, int index, IEnumerator numerator)	//开启单例携程
    {
        if (index < 0)
            Debug.LogWarning(" Should Not Add Coroutine Index Which Below 0");

        int targetIndex = CoroutineManager.QuestForIndex(target, index);
        if (CoroutineManager.Dic_Coroutines.ContainsKey(targetIndex))
            if (CoroutineManager.Dic_Coroutines[targetIndex] != null)
                CoroutineManager.Instance.StopCoroutine(CoroutineManager.Dic_Coroutines[targetIndex]);
            else
                CoroutineManager.Dic_Coroutines.Add(targetIndex, null);

        CoroutineManager.Dic_Coroutines[targetIndex] = CoroutineManager.Instance.StartCoroutine(numerator);
    }
    public static void StopSingleCoroutine(this ISingleCoroutine target, int index = 0)	//终止单例携程
    {
        int targetIndex = CoroutineManager.QuestForIndex(target, index);
        if (CoroutineManager.Dic_Coroutines.ContainsKey(targetIndex) && CoroutineManager.Dic_Coroutines[targetIndex] != null)
            CoroutineManager.Instance.StopCoroutine(CoroutineManager.Dic_Coroutines[targetIndex]);
    }

    public static void StopAllSingleCoroutines(this ISingleCoroutine target)		//终止单个接口申请的所有单例携程
    {
        int min=0, max = 0;
        CoroutineManager.QuestForRange(target,ref min,ref max);
        foreach (int index in CoroutineManager.Dic_Coroutines.Keys)
        {
            if (index >= min && index <= max)
                CoroutineManager.Instance.StopCoroutine(CoroutineManager.Dic_Coroutines[index]);
        }
    }

    public static void StopSingleCoroutines(this ISingleCoroutine target, params int[] indexes)		//终止多个携程
    {
        for (int i = 0; i < indexes.Length; i++)
            StopSingleCoroutine(target, indexes[i]);
    }
}

未来优化

1.还未进行容错处理,如申请一个超过999的ID会出现ID冲突
2.用int作为携程ID索引不是很直观,可以采用枚举代替
3.能够在此基础上实现DoTween的效果(用Transform代替接口与单例ID并增加从元函数)

该文章只能提供思路,个人学疏才浅,无法保证是否会产生性能问题.                           
                                                                                         --StriteR 2019/3/22

你可能感兴趣的:(Framework?)