在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;
}
}
}
个人理解的携程机制:
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