Unity中【UniTask异步流程】如何进行【步骤分段】、【步骤撤销】、【步骤跳转】、【取消异步任务】

本文介绍了Unity中UniTask与C#的Task,阐述了将原脚本异步流程改造的需求来源。通过将流程分块,实现了跳步操作,包括分类、实现方法、执行所有步骤及取消步骤。最后给出了测试步骤和脚本源码,为Unity开发中异步流程处理提供参考。

一、UniTask和Task

UniTask是Unity中的Task实现,Task是C#中实现异步操作的一个模块(类)。UniTask与Task有着同样的使用思路(使用习惯,常用API等),可以说UniTask是借鉴Task而开发出来的。

二、需求的来源

以前有一个实验,操作就是点击物体,执行动画,点击物体,执行动画…如此子子孙孙无穷循环,直到地球爆炸(实验结束)。

2.1 原来的脚本

于是很容易就用UniTask的await把所有操作连成一片,写在一个脚本里,甚至一整个实验就一个脚本。

比如下面:

1)、面板参数定义

面板用到的参数全部释放在Inspector上面,代码的话带上注释和空格将近1800行
在这里插入图片描述

2)、异步流程的组织

操作流程的话,写在一个异步方法里,浩浩荡荡写了上千行…写起来倒是比较滑溜了,但是调试和复用的话,就有点…
在这里插入图片描述
在这里插入图片描述

2.2 要改造成什么样

如果用户说他要【上一步】、【下一步】和【跳步】
思路:把一串流程按照操作逻辑分块,不同的块编一个号,放到一个执行列表里面。

1)、从前的脚本是这样:

/// <summary>
/// 主流程:所有流程连成一片,无法分步执行
/// </summary>
/// <returns></returns>
public async UniTask Flow()
{
   
   
    //第一步
    await UniTask.Delay(1000);
    //...

    //第二步
    await UniTask.Delay(1000);
    //...

    //第三步
    await UniTask.Delay(1000);
    //...

    //...

    //第N步
    await UniTask.Delay(1000);
    //...
}

2) 、分块思路

  • (1)定义一个列表StepInfosList,用来装载要执行的步骤。
    /// <summary>
    /// 步骤信息表:系列化到面板,用于调试和观察,后期执行
    /// </summary>
    [Header("步骤信息表")]
    public List<StepInfo> StepInfosList = new List<StepInfo>();

每一个节点StepInfo的结构如下:
在这里插入图片描述

3) 、分块后的脚本

/// <summary>
/// 步骤信息Class
/// </summary>
[Serializable]
public class StepInfo
{
   
   
    /// <summary>
    /// 当前序号
    /// </summary>
    [Header("当前步骤的序号")]
    public int index;

    /// <summary>
    /// 步骤的名字
    /// </summary>
    [Header("步骤的名字")]
    public string name;

    /// <summary>
    /// 正常流程
    /// </summary>
    public Func<UniTask> Flow;

    /// <summary>
    /// 恢复到【初始状态】的流程
    /// </summary>
    public Action Init;

    /// <summary>
    /// 跳到【结束状态】的流程
    /// </summary>
    public Action Final;
}
  • (2)拆分步骤

把脚本按照逻辑分成不同的块(步骤),装入到执行步骤列表里

/// <summary>
/// 添加步骤:新改的写法——各个步骤单独分开,逐个添加到执行列表里
/// </summary>
/// <param name="ctk"></param>
/// <returns></returns>
public async UniTask AddSteps(CancellationToken ctk)
{
   
   
    //第一步
    var step = StepInfosList.AddFlow("第一步");
    step.Flow = async () =>
    {
   
   
        Debug.Log("Flow() - 第一步");
        await UniTask.Delay(1000, cancellationToken: ctk);
    };   

    //第二步
    step = StepInfosList.AddFlow("第二步");
    step.Flow = async () =>
    {
   
   
        Debug.Log("Flow() - 第二步");
        await UniTask.Delay(1000, cancellationToken: ctk);
    }; 

    //第三步
    step = StepInfosList.AddFlow("第三步");
    step.Flow = async () =>
    {
   
   
        Debug.Log("Flow() - 第三步");
        await UniTask.Delay(1000, cancellationToken: ctk);
    };

    //第N步
    step = StepInfosList.AddFlow("第N步");
    step.Flow = async () =>
    {
   
   
        Debug.Log("Flow() - 第N步");
        await UniTask.Delay(1000, cancellationToken: ctk);
    };
}

三、跳步会有哪些操作

3.1 跳步的分类

在这里插入图片描述

3.2 跳步的实现

  • 【1】获取目标步骤信息
  • 【2】处理中间步骤的状态
  • 【3】执行目标步骤的流程
/// <summary>
/// 给定步骤名字,执行指定的步骤【所谓任意跳步】
/// </summary>
/// <param name="taskName"></param>
async UniTask RunTask(string taskName)
{
   
   
    if (cts.IsCancellationRequested)
    {
   
   
        Debug.Log("所有的任务已经被取消了!!");
        return;
    }

    //【1】获取目标步骤信息
    var targetStep = StepInfosList.First(x => x.name.Equals(taskName.Trim()));

    //【2】处理中间步骤的状态
    Debug.Log($"#################### 要执行的目标步骤为:targetStep = {
     
     targetStep.index}  {
     
     targetStep.name}  currentIndex = {
     
     currentIndex} ");
    if (currentIndex == targetStep.index)  //本步骤重新执行:恢复到本步骤初始状态
    {
   
   
        Debug.Log($"回到【{
     
     targetStep.name}】初始状态");
        if (targetStep.Init == null)
        {
   
   
            Debug.LogWarning($"步骤【
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值