? ? ? ? 靈感來自下面這本書的協程部分,因此我就自己嘗試寫了一個
? ? ? ?我的新書Unity3D游戲開發(第3版) | 雨松MOMO程序研究院
?? 如果你不知道什么是協程:unity保姆級教程之協同程序_unity協同-CSDN博客?
????一句話概括:協程就是單線程的異步操作,其作用于Unity的主線程
1.我寫了如下幾個功能(只展示無參數):
基礎校驗
private bool CheckCount(int count){if (count < 0){Debug.LogError("循環次數不能為負數!");return false;}return true;}private bool CheckTime(float time){if (time < 0){Debug.LogError("等待時間不能為負數!");return false;}return true;}
1.等待受縮放時間影響后的秒數
public void WaitTime(float waitTime, Action callback){if (CheckTime(waitTime)){StartCoroutine(WaitTimeHandle(waitTime, () => callback?.Invoke()));}}
2.等待不受縮放時間影響后的秒數
public void WaitRealTime(float waitTime, Action callback){if (CheckTime(waitTime)){StartCoroutine(WaitRealTimeHandle(waitTime, () => callback?.Invoke()));}}
2.按固定時間間隔循環執行
public void LoopTime(float spacing, int overNumber, Action callback){if (CheckTime(spacing) && CheckCount(overNumber)){StartCoroutine(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke()));}}
3.等待固定幀執行一次
public void WaitFrame(int frameCount, Action callback){if (CheckCount(frameCount)){StartCoroutine(WaitFrameHandle(frameCount, () => callback?.Invoke()));}}
4.進度反饋
public void WaitTimeWithProgress(float waitTime, Action<float> progressCallback, Action completeCallback){if (CheckTime(waitTime)){StartCoroutine(ProgressTimer(waitTime, progressCallback, completeCallback));}}private IEnumerator ProgressTimer(float duration, Action<float> progress, Action complete){float startTime = Time.time;while (Time.time - startTime < duration){progress?.Invoke((Time.time - startTime) / duration);yield return null;}complete?.Invoke();}
5.等待當前幀渲染結束執行回調(本幀執行)
public void WaitForEndOfFrame(Action callback){StartCoroutine(WaitForEndOfFrameHandle(callback));}private IEnumerator WaitForEndOfFrameHandle(Action callback){yield return new WaitForEndOfFrame();callback?.Invoke();}
2.總覽
? ? ? 回調函數我寫了無參 一參?兩參的版本 可以自行添加參數
using System;
using System.Collections;
using UnityEngine;public class TimeManager : MonoBehaviour
{private static TimeManager instance;public static TimeManager Instance => instance;private void Awake(){if (instance == null){instance = this;}}private bool CheckCount(int count){if (count < 0){Debug.LogError("循環次數不能為負數!");return false;}return true;}private bool CheckTime(float time){if (time < 0){Debug.LogError("等待時間不能為負數!");return false;}return true;}#region 等待固定時間秒/// <summary>/// 等待固定時間以后執行回調/// </summary>/// <param name="waitTime">等待時間(秒)</param>/// <param name="callback">回調函數</param>public void WaitTime(float waitTime, Action callback){if (CheckTime(waitTime)){StartCoroutine(WaitTimeHandle(waitTime, () => callback?.Invoke()));}}public void WaitTime<T>(float waitTime, T param, Action<T> callback){if (CheckTime(waitTime)){StartCoroutine(WaitTimeHandle(waitTime, () => callback?.Invoke(param)));}}public void WaitTime<T, K>(float waitTime, T param1, K param2, Action<T, K> callback){if (CheckTime(waitTime)){StartCoroutine(WaitTimeHandle(waitTime, () => callback?.Invoke(param1, param2)));}}private IEnumerator WaitTimeHandle(float waitTime, Action action){yield return new WaitForSeconds(waitTime);action?.Invoke();}#endregion#region 等待固定時間秒(不受縮放影響)/// <summary>/// 等待固定時間以后執行回調(不受Time.timeScale影響)/// </summary>/// <param name="waitTime">等待時間(秒)</param>/// <param name="callback">回調函數</param>public void WaitRealTime(float waitTime, Action callback){if (CheckTime(waitTime)){StartCoroutine(WaitRealTimeHandle(waitTime, () => callback?.Invoke()));}}public void WaitRealTime<T>(float waitTime, T param, Action<T> callback){if (CheckTime(waitTime)){StartCoroutine(WaitRealTimeHandle(waitTime, () => callback?.Invoke(param)));}}public void WaitRealTime<T, K>(float waitTime, T param1, K param2, Action<T, K> callback){if (CheckTime(waitTime)){StartCoroutine(WaitRealTimeHandle(waitTime, () => callback?.Invoke(param1, param2)));}}private IEnumerator WaitRealTimeHandle(float waitTime, Action action){yield return new WaitForSecondsRealtime(waitTime);action?.Invoke();}#endregion#region 按固定時間間隔循環執行public void LoopTime(float spacing, int overNumber, Action callback){if (CheckTime(spacing) && CheckCount(overNumber)){StartCoroutine(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke()));}}public void LoopTime<T>(float spacing, int overNumber, T param, Action<T> callback){if (CheckTime(spacing) && CheckCount(overNumber)){StartCoroutine(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke(param)));}}public void LoopTime<T, K>(float spacing, int overNumber, T param1, K param2, Action<T, K> callback){if (CheckTime(spacing) && CheckCount(overNumber)){StartCoroutine(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke(param1, param2)));}}private IEnumerator LoopTimeHandle(float spacing, int overNumber, Action action){for (int i = 0; i < overNumber; i++){yield return new WaitForSeconds(spacing);action?.Invoke();}}#endregion#region 等待固定幀執行一次public void WaitFrame(int frameCount, Action callback){if (CheckCount(frameCount)){StartCoroutine(WaitFrameHandle(frameCount, () => callback?.Invoke()));}}public void WaitFrame<T>(int frameCount, T param, Action<T> callback){if (CheckCount(frameCount)){StartCoroutine(WaitFrameHandle(frameCount, () => callback?.Invoke(param)));}}public void WaitFrame<T, K>(int frameCount, T param1, K param2, Action<T, K> callback){if (CheckCount(frameCount)){StartCoroutine(WaitFrameHandle(frameCount, () => callback?.Invoke(param1, param2)));}}private IEnumerator WaitFrameHandle(int frameCount, Action action){for (int i = 0; i < frameCount; i++){yield return null;}action?.Invoke();}#endregion#region 進度反饋public void WaitTimeWithProgress(float waitTime, Action<float> progressCallback, Action completeCallback){if (CheckTime(waitTime)){StartCoroutine(ProgressTimer(waitTime, progressCallback, completeCallback));}}private IEnumerator ProgressTimer(float duration, Action<float> progress, Action complete){float startTime = Time.time;while (Time.time - startTime < duration){progress?.Invoke((Time.time - startTime) / duration);yield return null;}complete?.Invoke();}public void WaitTimeWithProgress<T>(float waitTime, T param, Action<float, T> progressCallback, Action<T> completeCallback){if (CheckTime(waitTime)){StartCoroutine(ProgressTimer(waitTime, param, progressCallback, completeCallback));}}private IEnumerator ProgressTimer<T>(float duration, T param, Action<float, T> progress, Action<T> complete){float startTime = Time.time;while (Time.time - startTime < duration){progress?.Invoke((Time.time - startTime) / duration, param);yield return null;}complete?.Invoke(param);}public void WaitTimeWithProgress<T, K>(float waitTime, T param1, K param2, Action<float, T, K> progressCallback, Action<T, K> completeCallback){if (CheckTime(waitTime)){StartCoroutine(ProgressTimer(waitTime, param1, param2, progressCallback, completeCallback));}}private IEnumerator ProgressTimer<T, K>(float duration, T param1, K param2, Action<float, T, K> progress, Action<T, K> complete){float startTime = Time.time;while (Time.time - startTime < duration){progress?.Invoke((Time.time - startTime) / duration, param1, param2);yield return null;}complete?.Invoke(param1, param2);}#endregion#region 等待當前幀結束執行回調public void WaitForEndOfFrame(Action callback){StartCoroutine(WaitForEndOfFrameHandle(callback));}private IEnumerator WaitForEndOfFrameHandle(Action callback){yield return new WaitForEndOfFrame();callback?.Invoke();}public void WaitForEndOfFrame<T>(T param, Action<T> callback){StartCoroutine(WaitForEndOfFrameHandle(param, callback));}private IEnumerator WaitForEndOfFrameHandle<T>(T param, Action<T> callback){yield return new WaitForEndOfFrame();callback?.Invoke(param);}public void WaitForEndOfFrame<T, K>(T param1, K param2, Action<T, K> callback){StartCoroutine(WaitForEndOfFrameHandle(param1, param2, callback));}private IEnumerator WaitForEndOfFrameHandle<T, K>(T param1, K param2, Action<T, K> callback){yield return new WaitForEndOfFrame();callback?.Invoke(param1, param2);}#endregionpublic void Stop(IEnumerator func){StopCoroutine(func);}public void StopAll(){StopAllCoroutines();}public TimeChainContext StartChain(){return new TimeChainContext(this);}
}
3.Ai給出了如下拓展思路? ? ? ?
? ? ? ??優先級高
? ? ????鏈式調用擴展
????????物理時間步長同步
?????????優先級中
????????調試可視化工具
????????網絡同步時鐘
? ? ? ? 優先級低
?? ? ?自動化測試框架集成
??????使用Mono管理類去管理該腳本從而擺脫Mono的控制
? ? ? ? 我目前的需求沒有這么復雜,當作一個簡單的計時器使用
????????其是依賴于Unity的這一點可以用await和async來替代,但是可能涉及到了多線程,我這塊學了但是用的不多還需加強