一个unity 协程的帮助类

unity协程在写动画相关的代码时相当有用。但如果组织不当常常会导致思维混乱。这是一个使用协程的帮助类,利用装饰模式的思想最大化解耦。代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class IEM : MonoBehaviour {

    private IEnumerator iem = null;

    public IEnumerator getIenumerator()
    {
        return iem;
    }


    //使用装饰模式来嵌套功能链条
    //给一个协程增加执行前逻辑以及执行后逻辑
    private IEnumerator _ACT(IEnumerator i, Action after = null, Action before = null)
    {
        if (before != null)
            before();

        if (i != null)
            yield return StartCoroutine(i);

        if (after != null)
            after();
    }

    //延迟一定时间后执行
    private IEnumerator _DELAY(IEnumerator i, float time)
    {
        if (time > 0)
            yield return new WaitForSeconds(time);

        if (i != null)
            yield return StartCoroutine(i);

    }

    //执行后等待一定时间
    private IEnumerator _WAIT(IEnumerator i, float time)
    {
        if (i != null)
            yield return StartCoroutine(i);

        if (time > 0)
            yield return new WaitForSeconds(time);
    }

    //将两个协程链接在一起
    private IEnumerator _JOIN(IEnumerator start, IEnumerator end)
    {
        if (start != null)
            yield return StartCoroutine(start);

        if (end != null)
            yield return StartCoroutine(end);
    }

    public IEnumerator _WHILE(IEnumerator m, IEnumerator n)
    {
        Coroutine c = null;
        Coroutine d = null;
        if (m != null)
            c = StartCoroutine(m);
        if (n != null)
            d = StartCoroutine(n);

        yield return m;
        yield return n;
    }

    //使用装饰模式思想 制造一个协程链条 
    //为了保证数据正确 原则上应从start 开始 end结束
    //开始
    public static IEM START()
    {
        GameObject s = new GameObject();
        s.AddComponent<IEM>();
        IEM d = s.GetComponent<IEM>() as IEM;
        
        return d;
    }

    public static IEM START(IEnumerator enm)
    {
        GameObject s = new GameObject();
        s.AddComponent<IEM>();
        IEM d = s.GetComponent<IEM>() as IEM;
        d.iem = enm;
        
        return d;
    }

    //结束时开始执行协程  以及加入群组
    public IEM END()
    {
        if (iem == null)
            return this;

        StartCoroutine(iem);
        iem = null;

        return this;
    }

    public IEM END(int group)
    {
        if (iem == null)
            return this;

        Coroutine c = StartCoroutine(iem);
        CRTS.Instance.Add(group, c);
        iem = null;

        return this;
    }
    

    //增加行为
    public IEM ACT(Action after = null, Action before = null)
    {
        iem = _ACT(iem, after, before);
        return this;
    }
    //增加下一个协程
    public IEM AFTER(IEnumerator after)
    {
        iem = _JOIN(iem, after);
        return this;
    }
    public IEM AFTER(IEM after)
    {
        return AFTER(after.getIenumerator());
    }
    //增加上一个协程
    public IEM BEFORE(IEnumerator before)
    {
        iem = _JOIN(before, iem);
        return this;
    }
    public IEM BEFORE(IEM before)
    {
        return BEFORE(before.getIenumerator());
    }
    //增加延迟时间 延迟运行当前协程
    public IEM TIME_BEFORE(float time)
    {
        iem = _DELAY(iem, time);
        return this;
    }
    //完成协程后等待一定时间
    public IEM TIME_AFTER(float time)
    {
        iem = _WAIT(iem, time);
        return this;
    }
    //与其他协程共同运行
    public IEM WHILE(IEnumerator enm)
    {
        iem = _WHILE(iem, enm);
        return this;
    }
    public IEM WHILE(IEM enm)
    {
        return WHILE(enm.getIenumerator());
    }
    //注意 多个参数的while与单参数的while结果有巨大区别
    //使用参数的while 表明 是前述协程运行完毕后再共同运行,函数生成一个新的iem返回
    //而单参数的while表明与前述协程共同运行 在原IEM 基础上生效
    public static IEM WHILE(params IEnumerator[] senm)
    {
        IEM temp = null;
        foreach(IEnumerator i in senm)
        {
            if (i != null && temp == null)
                temp = IEM.START(i);
            else
                temp = temp.WHILE(i);
        }
        return temp;
    }
    public static IEM WHILE(params IEM[] senm)
    {
        IEM temp = null;
        foreach (IEM i in senm)
        {
            if (i != null && temp != null)
                temp = i;
            else
                temp = temp.WHILE(i);
        }
        return temp;
    }

    //判断分支 
    public IEM IF(Func<bool> act,IEnumerator t = null,IEnumerator f = null)
    {
        bool bb = act();
        
        if (bb)
            return AFTER(t);
        else
            return AFTER(f);
    }
    public IEM IF(Func<bool> act, IEM t, IEnumerator f = null)
    {
        return IF(act,t.getIenumerator(),f);
    }
    public IEM IF(Func<bool> act, IEnumerator t, IEM f)
    {

        return IF(act, t, f.getIenumerator());
    }
    public IEM IF(Func<bool> act, IEM t , IEM f )
    {

        return IF(act, t.getIenumerator(), f.getIenumerator());
    }

}
使用:比如一个三消游戏,棋子定义了 迭代器moveTo,棋盘定义了判断是否消除函数check则可以这样写代码:
IEM.START(g.MoveTo(l))
            .WHILE(l.MoveTo(g))
            .ACT(null, g.SetState_Switching).ACT(null, l.SetState_Switching)
            .TIME_AFTER(1.0f)
            .IF(check,IEM.START().ACT(g.SetState_death).ACT(l.SetState_death,IEM.WHILE(g.MoveTo(l),l.MoveTo(g)))
            .END();

从上到下,棋子g与棋子l交换,同时l与g交换,交换之前将棋子状态设置为交换状态,交换完毕后等待1秒,然后开始check函数判断是否可以消除,判断为真将g和l状态设置为death,判断为false则交换回去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值