• Unity常用协程功能封装


    # 1.前言
    unity开发过程中,经常用到一些特定的协程功能,比如延时触发、等待触发、重复操作等。unity自带Invoke以及InvokeRepeating方法,但这些方法均采用反射机制,性能消耗,而且代码混淆时极其容易出错。所以再次对这些功能做以下简单封装。方便后续使用。
    # 2.CoroutineJobCenter
    CoroutineJobCenter封装了需要的基本方法。
    ## 2.1 延时触发
    延时一定事件触发。
    ```csharp
    public IEnumerator StartJobDelayed(float delayedTime, Action action)
    {
    yield return new WaitForSeconds(delayedTime);

    if (action != null)
    {
    action();
    }
    }

    public IEnumerator StartJobDelayed<T>(float delayedTime, Action<T> action, T t)
    {
    yield return new WaitForSeconds(delayedTime);

    if (action != null)
    {
    action(t);
    }
    }
    ```
    ## 2.2 等待触发
    等待某一条件返回true时触发,采用unity自带的WaitUntil类。

    ```csharp
    public IEnumerator StartJobUntil(Func<bool> funtion, Action action)
    {
    yield return new WaitUntil(funtion);

    if (action != null)
    {
    action();
    }
    }

    public IEnumerator StartJobUntil<T>(Func<bool> funtion, Action<T> action, T t)
    {
    yield return new WaitUntil(funtion);

    if (action != null)
    {
    action(t);
    }
    }
    ```
    ## 2.3 重复触发
    ### 2.3.1 每隔一帧触发,并规定触发次数。

    ```csharp
    public IEnumerator RepeatJobPerFrame(int count, Action action)
    {
    for (int i = 0; i < count; i++)
    {
    yield return null;

    if (action != null)
    {
    action();
    }
    }
    }

    public IEnumerator RepeatJobPerFrame<T>(int count, Action<T> action, T t)
    {
    for (int i = 0; i < count; i++)
    {
    yield return null;

    if (action != null)
    {
    action(t);
    }
    }
    }
    ```
    ### 2.3.2 每隔固定时间触发,并规定触发次数。

    ```csharp
    public IEnumerator RepeatJobPerTimespan(int count, float interval, Action action)
    {
    yield return new RepeatJobPerTimespan(action, count, interval);
    }
    ```

    ```csharp
    public class RepeatJobPerTimespan : CustomYieldInstruction
    {
    private Action action;
    private int count;
    private int repeatCount;
    private float timeSpan;
    private float startedTime;

    public override bool keepWaiting
    {
    get
    {
    if (repeatCount >= count)
    {
    return false;
    }
    else if(Time.time - startedTime >= timeSpan)
    {
    startedTime = Time.time;
    repeatCount++;

    if (action != null)
    {
    action();
    }
    }

    return true;
    }
    }

    public RepeatJobPerTimespan(Action action, int count, float timeSpan)
    {
    this.action = action;
    this.count = count;
    this.timeSpan = timeSpan;
    startedTime = Time.time;
    repeatCount = 0;
    }
    }
    ```
    ### 2.3.3 规定时间内,间隔触发
    **注意:**
    由于间隔多长时间 触发的时间间隔并不精确,所以会影响触发次数。比如每隔两秒执行一次,一共执行六秒。则不会执行三次,因为每次等待两秒,根据判断肯定会超过两秒。所以不会有第三次执行。此时可以适当放宽总时间或者减小时间间隔。
    ```csharp
    public IEnumerator RepeatJobInCertainTimeSpan(float timeSpan, float interval, Action action)
    {
    yield return new RepeatJobInCertainTimespan(action, interval, timeSpan);
    }
    ```

    ```csharp
    public class RepeatJobInCertainTimespan : CustomYieldInstruction
    {
    private Action action;
    private float startTime;
    private float lastJobTime;
    private float interval;
    private float timeSpan;

    public override bool keepWaiting
    {
    get
    {
    if (Time.time - startTime > timeSpan)
    {
    return false;
    }
    else if (Time.time - lastJobTime >= interval)
    {
    lastJobTime = Time.time;

    if (action != null)
    {
    action();
    }
    }
    return true;
    }
    }

    public RepeatJobInCertainTimespan(Action action, float interval, float timeSpan)
    {
    this.action = action;
    this.interval = interval;
    this.timeSpan = timeSpan;
    this.startTime = Time.time;
    this.lastJobTime = Time.time;
    }
    }
    ```

    ## 2.4 规定的时间内等待触发
    这是一个比较常用的方法,比如超时等待。即如果在规定的时间内完成或者超过规定的时间,则进行下一步处理。

    ```csharp
    public IEnumerator WaitUntilInCertainTimespan(float timeSpan, Func<bool> function, Action action)
    {
    yield return new WaitUntilInCertaiTime(function, timeSpan);

    if (action != null)
    {
    action();
    }
    }
    ```

    ```csharp
    public class WaitUntilInCertaiTime : CustomYieldInstruction
    {
    private Func<bool> function;
    private float timeSpan;
    private float startTime;

    public override bool keepWaiting
    {
    get
    {
    if (function() || Time.time - startTime > timeSpan)
    {
    return false;
    }
    return true;
    }
    }

    public WaitUntilInCertaiTime(Func<bool> function,float timeSpan)
    {
    this.function = function;
    this.timeSpan = timeSpan;
    startTime = Time.time;
    }
    }
    ```
    # 3.应用

    ```csharp
    using CoroutineJob;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    public class CorountineJobTest : MonoBehaviour
    {
    public Button button;

    private bool flag = false;

    private void Start()
    {
    button.onClick.AddListener(OnStateChange);

    //StartCoroutine(CoroutineJobCenter.Instance.StartJobUntil(() => { return flag; }, () =>
    //{
    // Debug.Log("StartJobUntil");
    //}));

    //StartCoroutine(CoroutineJobCenter.Instance.RepeatJobPerTimespan(5, 2, () =>
    //{
    // Debug.Log("RepeatJobPerTimespan");
    //}));

    //StartCoroutine(CoroutineJobCenter.Instance.RepeatJobInCertainTimeSpan(6, 1.8f, () =>
    //{
    // Debug.Log("RepeatJobInCertainTimeSpan");
    //}));

    StartCoroutine(CoroutineJobCenter.Instance.WaitUntilInCertainTimespan(6, () => { return flag; }, () =>
    {
    Debug.Log("RepeatJobInCertainTimeSpan");
    }));
    }

    void OnStateChange()
    {
    flag = true;
    }

    }

    ```

  • 相关阅读:
    2020春,不一样的学期不一样的软工实践
    尘埃落下,我抓住透明的阳光,温暖留在掌心
    敏捷软工
    《构建之法》& CI/CD调研
    2021年-软件工程-热身阅读作业
    从学生到科技工作者
    希望我能帮到你:给同学们软件开发的建议
    CC2020 分享信息
    【计算机教育】看《计算机科学导论》,发展计算思维能力
    【计算机教育】创新工程实践课程的反馈
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/11764927.html
Copyright © 2020-2023  润新知