karsion / ActionSequenceSystem

A Unity3D C# multifunctional chaining timer system 一个U3D C# 多功能链式计时器
MIT License
68 stars 15 forks source link
chaining timer unity3d

license release

ActionSequenceSystem

A Unity3D C# multifunctional chaining timer system
一个U3D C# 多功能链式计时器

简要说明

注意事项

已知问题


设计架构

ActionSequenceSystem 序列系统

ActionSequence 序列

ActionNode 节点


使用方法

说明:下面使用方法中的this的类型为Component或其子类(其实this is MonoBehaviour)

延迟开关GameObject

既然用了Component来做ID,控制gameObject显示隐藏就是举手之劳,何乐而不为

//Start a toggle gameObject active/deactive sequence
tfShowHideExample.Shower(0.5f);
tfShowHideExample.Hider(1.5f);

//Start a infinite loop toggle active gameObject
tfShowHideExample.Sequence().Interval(0.5f).ToggleActive().Loop();

延迟开关Behaviour

Component转Behaviour,实现控制它的Enable

//Set enable to a Behaviour
this.Enabler(0.5f);
animator.Enabler(0.5f);

开启单次计时器(延迟)

//Start a once timer
this.Delayer(1, () => Debug.Log(1));
this.Sequence().Interval(1).Action(() => Debug.Log(1));//Same

//Allso use transform as a ID to start a sequence
transform.Delayer(1, () => Debug.Log(1));

开启计次计时器(次数)

//Start a loop timer
this.Looper(0.5f, 3, false, () => Debug.Log(-1));
this.Sequence().Loop(3).Interval(0.5f).Action(() => Debug.Log(-1));//Same

开启无限计时器

相当于计次计时器的缩写,循环次数设置为-1

//Start a infinite loop timer
this.Looper(1, i => Debug.Log("Infiniter" + i));

开启自定义序列

//Start a custom sequence
this.Sequence()
    .Interval(2)
    .Action(() => Debug.Log("Test1"))
    .Interval(3)
    .Action(() => Debug.Log("Test2"))
    .Interval(1)
    .Action(() => Debug.Log("Test3 end"));

//Check Q key per 0.2 seconds
this.Sequence()
    .Loop()
    .Interval(0.2f)
    .WaitFor(() => Input.GetKeyDown(KeyCode.Q))
    .Action(n => Debug.Log("Q键 按下次数" + n));

停止序列

//Stop the sequence with the specified ID
private ActionSequence sequence;
sequence = this.Looper(0.5f, 3, false, () => Debug.Log(-1));
sequence.Stop(this);

//Stop all sequences by this ID
this.StopSequence();

//Allso transform as ID
transform.StopSequence();

UnscaledTime

//Start a once unscaled timer
this.Delayer(1, () => Debug.Log(1)).Unscaled();

IAction

用接口代替委托,因为委托通常都会闭包

public class User : MonoBehaviour, IAction
{
    private int times;
    public void OnEnable()
    {
        this.Delayer(1, this, 0);
        this.Looper(1, this, 1);
    }

    public void Action(int id, int loopTime)
    {
        switch (id)
        {
            case 0:
                //Do something when id is 0
                break;
            case 1:
                times++;
                Debug.Log(times);
                break;
        }
    }
}

可以不用ID直接开序列

//Start a sequence without id.
ActionSequenceSystem.Delayer(5, () => Debug.Log("No id delayer"));
ActionSequenceSystem.Looper(0.2f, 10, false, () => Debug.Log("No id looper"));

//Notes:An instance must be preserved to manually stop an infinite loop sequence.
ActionSequenceHandle infiniteSequenceHandle = new ActionSequenceHandle();
ActionSequenceSystem.Looper(0.2f, -1, false, () => Debug.Log("No id infinite looper")).SetHandle(infiniteSequenceHandle);
infiniteSequenceHandle.StopSequence();

停止序列特殊技巧:ActionSequenceHandle用法

简单来说就是引用一个计时器,让我们可以随时手动停止它
但ActionSequence自身有停止的方法,为什么还要使用ActionSequenceHandle?
ActionSequenceHandle是为了处理“开启全局计时器时不传入ID,又要控制这个计时器”的情况

public class ActionSequenceHandleExample : MonoBehaviour
{
    private readonly ActionSequenceHandle infiniteSequenceHandle = new ActionSequenceHandle();
    private ActionSequence sequence;

    private void Start()
    {
        //Notes:An instance must be preserved to manually stop an infinite loop sequence.
        ActionSequenceSystem.Looper(infiniteSequenceHandle, 0.2f, -1, false, () => Debug.Log("No id infinite looper"));
        sequence = this.Looper(0.5f, 3, false, () => Debug.Log("this looper"));
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.B))
        {
            //使用ActionSequenceHandle停止
            infiniteSequenceHandle.StopSequence();
            //使用ActionSequence停止
            sequence.Stop(this);
            this.StopSequence(sequence);//Same as sequence.Stop(this);
        }

        if (Input.GetKeyDown(KeyCode.X))
        {
            transform.Looper(infiniteSequenceHandle, 1, 5, false, i =>
            {
                if (i == 2)
                {
                    infiniteSequenceHandle.StopSequence();
                }
            });
        }
    }
}