Unity协程返回值的解决方案

问题背景

协程返回IEnumerator,无其他返回值,且不能用out ref参数。

我们经常需要协程返回值,常用方案有传入委托。在不太复杂的场景下够用。最简单的有传入一个无参委托,再完善点传入UnityAction<bool>,根据成功失败执行不同操作。

什么情况下会不够用呢?当我们需要一个协程接一个协程,而且根据前一个协程的结果不同,后面的操作不一样,可能成功失败一个用协程一个不用协程,也可能用不同的协程。

典型的应用场景就是热更新检查。

这时候再传入回调写就变成回调套娃。

然后我们想到把这一系列操作的顶层做成IEnumerator,里面用yield return IEnumerator控制流程,解决了套娃的问题。然后遇到开头说的IEnumerator返回值的问题。

然后我们想到肯定是通过输入参数返回值,out ref不能用,然后两条路:传入委托、传入class(引用类型)。

然后传入委托面临委托的数量、参数列表设计的问题。

传入回调:回调个数和参数列表的设计

一般操作都要返回成功失败,那么回调可以一个UnityAction<bool>,或者两个UnityAction。然后失败时我还想要报错信息,于是传入一个UnityAction<bool,string>或者两个回调:UnityAction、UnityAction<string>。

然后对应成功的操作我也想打印日志。那么要么弄3个委托,要么一个结果委托+一个打印日志委托。

然后返回结果的UnityAction<bool>从外面传进来,里面的操作不能直接用,因为子操作成功不代表整个操作成功,需要所有子操作成功才最终成功,但是子操作失败会导致直接失败。

然后子操作的UnityAction<bool>需要临时做一个?然后发现后续的代码要写到前面,变成了跟回调套娃一样的问题:代码执行顺序和阅读顺序不一致!

然后还是想,能不能像写同步函数那样写连续的、根据结果执行不同分支的异步操作???

传入class(引用类型)

返回最基本的成功失败,就用class封装一个bool。然后还会有很多其他类型,只能用到什么类型封装一个什么class?

不想类爆炸多,弄一个泛型类。然后想返回多个值可以用ValueTuple,或者再封装。

cs 复制代码
public class AsyncReturn<T>
{
    public bool ok;
    public string errorMsg;
    public T data;
}

StartCoroutine和yield return

一个协程可以被StartCoroutine调用也可以被yield return调用。被StartCoroutine时只能通过传入回调指定后续操作,而yield return调用可以把后续操作写在后面更清晰,返回值通过传入class。

为了兼容这两种情况,可以把返回值class和回调都传入。那么StartCoroutine调用时返回值class和回调都要传入,yield return调用可以回调给null。

cs 复制代码
/// <summary>
/// 如果用于yield return的IEnumerator,则使用AsyncReturn放返回值;
/// 如果用于StartCoroutine,则使用回调。
/// </summary>
/// <param name="url"></param>
/// <param name="ret"></param>
/// <returns></returns>
IEnumerator GetTextIE(string url,AsyncReturn<string>ret,
    UnityAction<AsyncReturn<string>>callback) {
    UnityWebRequest req = UnityWebRequest.Get(url);
    yield return req.SendWebRequest();
    if (req.result == UnityWebRequest.Result.Success)
    {
        ret.data=req.downloadHandler.text;
        ret.ok=true;
    }
    else
    {
        ret.ok=false;
        ret.errorMsg=$"获取失败:{req.result} {req.error} {req.responseCode}";
    }
    callback?.Invoke(ret);
}
相关推荐
WiChP1 天前
【V0.1B15】从零开始的2D游戏引擎开发之路
游戏引擎
zhchyun20082 天前
# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)
ui·unity·游戏引擎
Behaviour3 天前
Unity游戏HybridCLR 热更新接入实战
游戏·unity·游戏引擎
LONGZETECH3 天前
新能源汽车动力电池实训教学痛点与虚拟仿真技术解决方案
c语言·3d·unity·架构·汽车·汽车教学软件
王维志3 天前
UiSplineRenderer
unity·游戏引擎
k4m7v2pz3 天前
Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复
游戏引擎·godot·相机·缩放·clamp·camera2d
FairGuard手游加固3 天前
iOS 游戏加固技术解析:代码混淆、资源加密、内存保护与重签名检测
安全·游戏·macos·unity·ios·objective-c
k4m7v2pz4 天前
Godot 4 窗口拉伸黑边与变形:stretch 配置全解析
数码相机·游戏引擎·godot·2d游戏·黑边·stretch·画面比例
UWA4 天前
GPM 2.0 WebGL 监测能力扩容|覆盖 Unity/Cocos/LayaAir 多引擎微信 & 抖音小游戏
unity·微信·性能优化·小游戏·webgl
Behaviour4 天前
Unity 手游网络同步技术
网络·unity·c#·游戏引擎