VCoroutine
Avalon712/VCoroutine: C# Coroutine
https://github.com/Avalon712/VCoroutine
功能介绍
- 协程不依赖Unity的MonoBehaviour,内部自己管理协程的运行,你可以在任意地方开启一个协程(Run)、暂停一个协程(Stop,注:与Unity的Stop不一样的是,Stop不会杀死协程,你仍然可以通过Resume来恢复他的执行),恢复协程运行(Resume)、杀死一个协程(Kill);
- 支持yield return Task,只有异步任务完成后才会继续执行后续步骤;
- 可以设置依赖关系,当协程A的运行需要协程B、C都运行玩时才能执行,同时协程B、C的运行都互相不依赖,只有等待B、C都完成后协程A才会开始执行(与Unity中的Job System中的任务调度依赖关系原理一致);
- 可以自定义扩展,你可以扩展yield return类型的处理方式,以及为每个协程的运行单独设置yield处理器上下文对象;
安装方式
通过PackManager选中add package from git URL即可。
使用举例
1、对Unity内置的yield指令全部支持
cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using CysharpCoroutine;
public sealed class FuncTest : MonoBehaviour
{
void Start()
{
TestVCoroutine().RunAsCoroutine();
}
private IEnumerator TestVCoroutine()
{
Debug.Log($"{nameof(TestVCoroutine)} Start");
yield return new WaitForEndOfFrame();
print(VCoroutine.Environment.ToString());
int i = 0;
while (++i < 10)
{
yield return null;
print(VCoroutine.Environment.ToString());
}
yield return new WaitForFixedUpdate();
print(VCoroutine.Environment.ToString());
yield return new WaitUntil(() => ++i >= 30);
Debug.Log(i);
yield return new WaitWhile(() => ++i >= 50);
Debug.Log(i);
yield return new Func<bool>(() => ++i >= 100);
Debug.Log(i);
UnityWebRequest request = UnityWebRequest.Get("https://www.baidu.com");
yield return request.SendWebRequest();
print(request.downloadHandler.text);
yield return Task.Run(() => { while (++i <= 100000) { } });
Debug.Log(i);
Debug.Log("WaitForSecondsRealtime Start");
yield return new WaitForSecondsRealtime(3);
Debug.Log("WaitForSecondsRealtime End");
yield return TestVCoroutine2();
yield return TestVCoroutine3(); //支持泛型
Debug.Log("WaitForSeconds Start");
yield return new WaitForSeconds(5);
Debug.Log("WaitForSeconds End");
Debug.Log($"{nameof(TestVCoroutine)} End");
}
private IEnumerator TestVCoroutine2()
{
Debug.Log($"{nameof(TestVCoroutine2)} Start");
yield return new WaitForSecondsRealtime(3);
Debug.Log($"{nameof(TestVCoroutine2)} End");
}
private IEnumerator<Func<bool>> TestVCoroutine3()
{
int i = 0;
Debug.Log($"{nameof(TestVCoroutine3)} Start");
yield return () => ++i >= 100;
Debug.Log(i);
Debug.Log($"{nameof(TestVCoroutine3)} End");
}
}
2、自定义扩展
cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CysharpCoroutine;
public sealed class ExtensionTest : MonoBehaviour
{
/// <summary>
/// 创建一个自定义的处理器上下文,处理定时回调功能
/// </summary>
private readonly CoroutineYieldHandleContext _timerYieldHandlerContext = new CoroutineYieldHandleContext(new List<YieldHandler>(){new YieldFloat()});
private void Awake()
{
CoroutineYieldHandleContext.RegisterHandlerToDefaultContext(new YieldFloat()); //注册到默认的yield处理器上下文中
}
void Start()
{
TestWaitTime().RunAsCoroutine();
TestTimer().RunAsCoroutine(_timerYieldHandlerContext); //使用自定义的处理器上下文处理协程的返回类型
}
IEnumerator TestWaitTime()
{
print("TestWaitTime Start");
yield return 5f; //等待5秒
print("TestWaitTime End");
}
IEnumerator TestTimer()
{
yield return 10f; //等待10秒后再开始执行,默认延时效果
print("TestTimer Start");
yield return 1f;
print("TestTimer End");
}
/// <summary>
/// 当yield return float时表示等待指定的秒数
/// </summary>
private sealed class YieldFloat : YieldHandler
{
public override Type YieldType => typeof(float);
protected override bool HandleYield(VCoroutine.CoroutineRecorder recorder)
{
float seconds = (float)recorder.Yield - Time.deltaTime;
recorder.Yield = seconds;
return seconds <= 0;
}
}
}
3、依赖队列
cs
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using CysharpCoroutine;
public sealed class DependencyTest : MonoBehaviour
{
void Start()
{
/*
依赖拓扑图
A
|----B
| |----C
| | |----F
| |----E
|----D
*/
CoroutineID a = VCoroutine.Run(A());
CoroutineID b = VCoroutine.Run(B());
CoroutineID c = VCoroutine.Run(C());
CoroutineID d = VCoroutine.Run(D());
CoroutineID e = VCoroutine.Run(E());
CoroutineID f = VCoroutine.Run(F());
VCoroutine.CombineDependencies(a, true, b, d);
VCoroutine.CombineDependencies(b, true, c, e);
VCoroutine.CombineDependency(c,f);
// VCoroutine.CombineDependency(f, a, false); //循环依赖,没有检测循环依赖,会导致所有依赖A的协程都无法运行
}
IEnumerator A()
{
print("A Start");
yield return new WaitForSeconds(3);
print("A End");
}
IEnumerator B()
{
print("B Start");
yield return new WaitForSeconds(3);
print("B End");
}
IEnumerator C()
{
print("C Start");
yield return Task.Delay(3000);
print("C End");
}
IEnumerator D()
{
print("D Start");
UnityWebRequest request = UnityWebRequest.Get("https://www.baidu.com");
yield return request.SendWebRequest();
print("D End");
}
IEnumerator E()
{
print("E Start");
ResourceRequest request = Resources.LoadAsync<GameObject>("Res");
yield return request;
Instantiate(request.asset);
print("E End");
}
IEnumerator F()
{
print("F Start");
yield return new WaitForFixedUpdate();
print("F End");
}
}