工具随记-协程

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

public class GameStart : MonoBehaviour
{
    public CallbackRunnerTest callbackRunnerTest;

    private GameRoot gameRoot;

    private void Start()
    {
        gameRoot = GameRoot.Instance;
        gameRoot.DebugTest();
        gameRoot.Test_RandomFloat(0.1f, 0.99f);
        gameRoot.Test_RandomInt(1, 9);
        gameRoot.Test_LogNewGuid();

        callbackRunnerTest.RunFiveSecondsRoutine();
        callbackRunnerTest.RunFiveSecondsRoutineAfter2Secs();
        callbackRunnerTest.RunNormalFunctionAsCallback();
        callbackRunnerTest.RunNormalFunctionAsCallbackAfter2Secs();
        callbackRunnerTest.CancelLatestCoroutine();
    }

    private void OnDestroy()
    {
        gameRoot.callbackRunner.StopAllCoroutines();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ED;

public class GameRoot : BaseMonoSingleton
{
    public CallbackRunner callbackRunner;

    private RangedFloat rangedFloat;
    private RangedInt RangedInt;


    protected override void Init()
    {
        base.Init();
        Debug.Log($"*********{this.GetType()} Init********");
    }

    public void DebugTest()
    {
        Debug.Log("*********Test********");
    }

    public void Test_RandomFloat(float min, float max)
    {
        rangedFloat = new RangedFloat
        {
            MinValue = min,
            MaxValue = max
        };
        float temp_Float = rangedFloat.Random();
        Debug.Log($"随机到的Float数值为:{temp_Float}");
    }

    public void Test_RandomInt(int min, int max)
    {
        RangedInt = new RangedInt
        {
            MinValue = min,
            MaxValue = max
        };
        float temp_Int = RangedInt.Random();
        Debug.Log($"随机到的Int数值为:{temp_Int}");
    }

    public void Test_LogNewGuid()
    {
        Debug.Log($"随机到的Guid数值为:{callbackRunner.LogGuid().ToString()}");
    }
}
using ED;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CallbackRunnerTest : MonoBehaviour
{
    private Guid _latestCoroutineKey;
    public void RoutineStarted(Guid key)
    {
        Debug.Log($"[Event Received: Started] Coroutine with key {key} started.");
    }

    public void RoutineFinished(Guid key)
    {
        Debug.Log($"[Event Received: Finished]Coroutine with key {key} finished.");
    }

    public void RoutineStopped(Guid key)
    {
        Debug.Log($"[Event Received: Stopped] Coroutine with key {key} stopped.");
    }

    public void RunFiveSecondsRoutine()
    {
        _latestCoroutineKey = CallbackRunner.Instance.StartCoroutineImmediately(CountFiveSeconds);
    }

    public void RunFiveSecondsRoutineAfter2Secs()
    {
        _latestCoroutineKey = CallbackRunner.Instance.StartCoroutineAfterDelay(2, CountFiveSeconds);
    }

    public void RunNormalFunctionAsCallback()
    {
        _latestCoroutineKey = CallbackRunner.Instance.StartCoroutineImmediately(GetFirst100FibonacciNumbers);
    }

    public void RunNormalFunctionAsCallbackAfter2Secs()
    {
        _latestCoroutineKey = CallbackRunner.Instance.StartCoroutineAfterDelay(2, GetFirst100FibonacciNumbers);
    }

    public void CancelLatestCoroutine()
    {
        Debug.Log(CallbackRunner.Instance.StopCoroutine(_latestCoroutineKey)
            ? $"Coroutine with key {_latestCoroutineKey} stopped."
            : $"Coroutine with key {_latestCoroutineKey} not found.");
    }

    /// 
    /// 数五秒
    /// 
    private IEnumerator CountFiveSeconds()
    {
        var seconds = 0;

        while (seconds < 5)
        {
            Debug.Log($"{seconds} seconds passed.");
            yield return new WaitForSeconds(1);
            seconds++;
        }
    }

    /// 
    /// 获得前100个斐波那契数
    /// 
    private void GetFirst100FibonacciNumbers()
    {
        const int count = 100;
        int n1 = 0, n2 = 1, n3;

        var fibonacciSequence = new List { n1, n2 }; // 列表来保存斐波那契数列

        for (var i = 2; i < count; ++i)
        {
            n3 = n1 + n2;
            fibonacciSequence.Add(n3);
            n1 = n2;
            n2 = n3;
        }

        // 用空格分隔符连接列表中的所有数字并打印它们
        Debug.Log($"First {count} Fibonacci numbers:");
        Debug.Log(string.Join(" ", fibonacciSequence));
    }

}

using UnityEngine;

namespace ED
{
    public abstract class BaseMonoSingleton : MonoBehaviour where T : BaseMonoSingleton
    {
        private static T _instance;

        public static T Instance => _instance;

        protected virtual void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(gameObject);
                return;
            }
            _instance = (T)this;
            Init();
        }

        protected virtual void Init() { }
    }
}

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

namespace ED
{
    /// 
    /// 只读属性。使用这个属性使一个字段在检查器中只能读取。
    /// 
    public class InspectorReadOnlyAttribute : PropertyAttribute { }

    public class CallbackRunner : BaseMonoSingleton
    {
        /// 
        ///当协程启动时调用。
        /// Guid是协程的Key。
        /// 
        [SerializeField]
        private UnityEvent onCoroutineStarted;

        /// 
        ///在协程完成时调用。
        /// Guid是协程的Key。
        /// 
        [SerializeField] private UnityEvent onCoroutineFinished;

        /// 
        ///当协程被代码停止时调用。
        /// Guid是协程的Key。
        /// 
        [SerializeField] private UnityEvent onCoroutineStopped;

        private bool IsCoroutineCancelled(Guid key) => !_routineIDict.ContainsKey(key);
        private static Guid GetCoroutineKey() => Guid.NewGuid();
        private IDictionary _routineIDict;


        [Space(10), Header("Debug Settings")]
        [SerializeField]
        private bool enableDebugLog;
        [SerializeField]
        private bool enableRoutineKeyRuntimeInfo;
        [SerializeField, InspectorReadOnly]
        private List runningCoroutineKeys;

        protected override void Init()
        {
            base.Init();
            _routineIDict = new Dictionary();
        }

        /// 
        /// 立即启动一个协程,并返回一个键,可以用来稍后取消这个协程。
        /// 
        public Guid StartCoroutineImmediately(Func coroutine)
        {
            var newKey = GetCoroutineKey();
            StartCoroutine(StartManagedCoroutine(coroutine, newKey));
            return newKey;
        }

        /// 
        /// 立即启动协程并返回可用于稍后取消该例程的键。
        /// 
        /// 将在协程中执行的操作
        public Guid StartCoroutineImmediately(Action action)
        {
            var newKey = GetCoroutineKey();
            StartCoroutine(StartManagedCoroutine(WrapActionInEnumerator(action), newKey));
            return newKey;
        }

        /// 
        /// 将在延迟后运行。该协程的键将立即返回。
        /// 
        /// 运行操作之前的等待时间。
        /// 将被执行的委派。
        public Guid StartCoroutineAfterDelay(float delay, Action action)
        {
            var newKey = GetCoroutineKey();
            StartCoroutine(StartManagedCoroutine(WrapActionInEnumerator(action), newKey, delay));
            return newKey;
        }

        /// 
        /// 将在延迟后运行。该协程的键将立即返回。
        /// 
        public Guid StartCoroutineAfterDelay(float delay, Func routine)
        {
            var newKey = GetCoroutineKey();
            StartCoroutine(StartManagedCoroutine(routine, newKey, delay));
            return newKey;
        }

        /// 
        /// 尝试根据提供的键停止协程。
        /// 
        /// Coroutine key
        /// 如果键存在并且例程已停止,则为True,否则为false。
        public bool StopCoroutine(Guid coroutineKey)
        {
            if (coroutineKey == Guid.Empty || !_routineIDict.ContainsKey(coroutineKey)) return false;
            StopCoroutine(_routineIDict[coroutineKey]);
            Log($"Coroutine '{coroutineKey}' stopped");
            onCoroutineStopped?.Invoke(coroutineKey);
            RemoveCoroutine(coroutineKey);
            return true;
        }

        public void StopCoroutine()
        {
            foreach (Guid item in _routineIDict.Keys)
            {
                StopCoroutine(item);
            }
        }

        public Guid LogGuid()
        {
            var newKey = GetCoroutineKey();
            return newKey;
        }

        #region 私有函数

        private void Log(string message)
        {
            if (!enableDebugLog) return;

            Debug.Log(message);
        }

        private IEnumerator StartManagedCoroutine(Func action, Guid coroutineKey, float? delay = null)
        {
            if (!IsCoroutineCancelled(coroutineKey)) yield break;
            if (delay.HasValue)
            {
                Log($"将例行程序延迟{delay.Value}秒开始");

                var delayCoroutine = StartCoroutine(WaitForDelay(delay.Value));
                RegisterNewCoroutine(coroutineKey, delayCoroutine);
                yield return delayCoroutine;
                RemoveCoroutine(coroutineKey);
            }

            Log($"Coroutine '{coroutineKey}' started");
            onCoroutineStarted.Invoke(coroutineKey);

            var coroutine = StartCoroutine(action());

            RegisterNewCoroutine(coroutineKey, coroutine);

            yield return coroutine;

            Log($"Coroutine '{coroutineKey}' finished");
            onCoroutineFinished?.Invoke(coroutineKey);
            RemoveCoroutine(coroutineKey);
        }

        private static IEnumerator WaitForDelay(float delay)
        {
            yield return new WaitForSeconds(delay);
        }

        /// 
        /// 注册新的协程
        /// 
        private void RegisterNewCoroutine(Guid coroutineKey, Coroutine runningCoroutine)
        {
            _routineIDict.Add(coroutineKey, runningCoroutine);
            if (!enableRoutineKeyRuntimeInfo) return;
            runningCoroutineKeys.Add(coroutineKey.ToString());
        }

        private void RemoveCoroutine(Guid coroutineKey)
        {
            if (!IsCoroutineCancelled(coroutineKey))
            {
                _routineIDict.Remove(coroutineKey);
            }
            if (!enableRoutineKeyRuntimeInfo) return;
            runningCoroutineKeys.Remove(coroutineKey.ToString());
        }

        private static Func WrapActionInEnumerator(Action action)
        {
            IEnumerator Wrapper()
            {
                action();
                yield return null;
            }

            return Wrapper;
        }
        #endregion
    }
}

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

namespace ED
{
    public abstract class RangedNumeric where T : struct
    {
        public T MinValue;
        public T MaxValue;

        public abstract T Random();
    }

    /// 
    /// 包含MaxValue的float类型
    /// 
    public class RangedFloat : RangedNumeric
    {
        public override float Random()
        {
            return UnityEngine.Random.Range(MinValue, MaxValue);
        }
    }

    /// 
    /// 包含MaxValue的int类型
    /// 
    public class RangedInt : RangedNumeric
    {
        public override int Random()
        {
            return UnityEngine.Random.Range(MinValue, MaxValue + 1);
        }
    }
}

工具随记-协程_第1张图片

你可能感兴趣的:(unity)