using System;
using System.Collection;
using System.Collection.Gernic;
using UnityEngine;
// 感谢唐老师的指导
public class YieldInstruction
public IEnumerator ie;
public float executeTime;
public class CoroutineMgr : MonoBehaviour
private List<YieldInstruction> list = new List<YieldInstruction>();
public void StartCoroutine(IEnumerator ie)
ie.MoveNext();
if((ie.Current is null) || (ie.Current is int))
list.Add(new YieldInstruction ie=ie,executeTime=0; );
else if(ie.Current is WaitForSeconds)
list.Add(new YieldInstruction
ie=ie,
executeTime=Time.time+(ie.Currentas WaitForSeconds).second );
else if (...)
...
void Update()
// 倒序遍历方便移除
for(int i=list.Count-1; i>=0; i--)
if(list[i].executeTime<=Time.time)
if(list[i].ie.MoveNext())
// 如果是已定义的类型
if((ie.Current is null)
|| (ie.Current is int))
|| (ie.Current is WaitForSeconds))
// 继续指定执行时机
else
list.RemoveAt(i);
else
list.RemoveAt(i);
public class TestMono : MonoBehaviour
public int times = 100000;
public bool useStr = true;
void Start()
for (int i = 0; i < times; i++)
if (useStr)
StartCoroutine("CoroutineFunc");
else
StartCoroutine(CoroutineFunc());
IEnumerator CoroutineFunc()
yield return null;
实验数据取 Unity Profiler 5秒内 GC Used Memory 最高点
项目/实验次数
1
2
3
4
5
6
不启动协程
13.1M
11.8M
12.2M
12.1M
12.4M
12.4M
传入字符串
24.0M
28.0M
27.7M
28.1M
28.4M
28.2M
传入IEnumerator
28.6M
28.2M
28.7M
28.5M
28.6M
28.5M
小结: 使用协程的确会产生垃圾, 且两种方式产生的内存不相上下.
2. 协程的垃圾产生在迭代器还是调度器?
由于调度器调度不存在的函数会报错, 所以只能从迭代器入手进行测试.
实验代码:
public class TestMono : MonoBehaviour
public int times = 100000;
public bool useStr = true;
// Start is called before the first frame update
void Start()
for (int i = 0; i < times; i++)
if (useStr)
enumerator = "CoroutineFunc";
else
CoroutineFunc();
IEnumerator CoroutineFunc()
yield return null;
public class TestMono : MonoBehaviour
public int times = 100000;
private IEnumerator enumerator;
// Start is called before the first frame update
void Start()
enumerator = CoroutineFunc();
for (int i = 0; i < times; i++)
StartCoroutine(enumerator);
IEnumerator CoroutineFunc()
yield return null;