Unity 封装一个依赖于MonoBehaviour的计时器(下) 链式调用

[Unity] 封装一个依赖于MonoBehaviour的计时器(上)-CSDN博客

目录

1.加入等待间隔时间"永远'执行方法

   2.修改为支持链式调用

实现链式调用

管理"链式"调度顺序

  3.测试       

        即时方法​编辑

        "永久"方法 

        链式调用 

​4.总结


1.加入等待间隔时间"永远'执行方法

      我将这个计时器修改为了支持链式调用,不过我还是发现了一个问题,有些地方的计时器要求是这样子的

using UnityEngine;public class RegularTimer : MonoBehaviour
{private float timer = 0f;public float targetTime = 5f;private void Update(){timer += Time.deltaTime;if (timer >= targetTime){// 达到目标时间,执行相应操作Debug.Log("Timer reached!");timer = 0f;}}
}

        但是我的协程计时器之中并没有随游戏"无限"进行的间隔计时器

        所以添加了一个无限循环执行的函数

 #region 无限循环执行/// <summary>/// 按固定时间间隔无限循环执行回调/// </summary>/// <param name="spacing">时间间隔(秒)</param>/// <param name="callback">回调函数</param>public void LoopForever(float spacing, Action callback){if (CheckTime(spacing)){StartCoroutine(LoopForeverHandle(spacing, () => callback?.Invoke()));}}public void LoopForever<T>(float spacing, T param, Action<T> callback){if (CheckTime(spacing)){StartCoroutine(LoopForeverHandle(spacing, () => callback?.Invoke(param)));}}public void LoopForever<T, K>(float spacing, T param1, K param2, Action<T, K> callback){if (CheckTime(spacing)){StartCoroutine(LoopForeverHandle(spacing, () => callback?.Invoke(param1, param2)));}}private IEnumerator LoopForeverHandle(float spacing, Action action){while (true){yield return new WaitForSeconds(spacing);action?.Invoke();}}#endregion

   2.修改为支持链式调用

       有两个要点:

       实现链式调用

        先别管怎么去写 看看怎么使用

     TimeManager.Instance.BeginChain().WaitTime().WaitRealTime();

        如果想要每一次"点"出后面的方法 要求是Instance一致

        所以要是方法的返回值是本身不就行了

    public TimeManager BeginChain(){enumeratorQ.Clear();//别管这一句return this;}

        完美解决问题 

        管理"链式"调度顺序

         因为链式调用是多个且有序的,所以一定要有个容器去存储,我画个图

         所以有没有想起什么? 先进先出 队列不就是这样的吗?

        en造数据结构与算法 c#语言 数组实现队列很难???看我一击破之!!!-CSDN博客

  // 链式调用的队列private Queue<IEnumerator> enumeratorQ = new Queue<IEnumerator>();private bool isChaining; // 是否正在执行队列

        然后就是自己解决如何去跑了 ,很简单,有调用就入队,跑起来就出队,全权由该队列管理即可

   

  public TimeManager BeginChain(){enumeratorQ.Clear();return this;}/// <summary>/// 开始执行链式调用/// </summary>private void ExecuteChain(){if (!isChaining && enumeratorQ.Count > 0){StartCoroutine(RunChain());}}/// <summary>/// 出队跑/// </summary>/// <returns></returns>private IEnumerator RunChain(){isChaining = true;while (enumeratorQ.Count > 0){yield return StartCoroutine(enumeratorQ.Dequeue());}isChaining = false;}
 public TimeManager WaitTime(float waitTime, Action callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitTimeHandle(waitTime, () => callback?.Invoke()));ExecuteChain();}return this;}

  3.测试       

        即时方法

        

"永久"方法 

   private void Start(){//1秒后执行TimeManager.Instance.LoopForever(1,Callback);}private void Callback() { Debug.Log("我是哈基咩");}

链式调用 

using System;
using UnityEngine;public class Test : MonoBehaviour
{private void Start(){// 链式调用测试TimeManager.Instance.BeginChain()// 1秒后执行 Callback.WaitTime(1f, Callback)// 等待120帧后执行 Callback1,并传递字符串参数.WaitFrame<string>(120, "在120帧后执行", Callback1)// 本帧结束时执行 Callback2,传递int和string参数.WaitForEndOfFrame<int, string>(520, "在本帧调的最后执行", Callback2)// 等待5秒,过程中反馈进度(Progress),完成后执行 Callback.WaitTimeWithProgress(5f, Progress, Callback);}private void Callback(){Debug.Log("我是哈基咩");}private void Callback1(string param1){Debug.Log($"帧:{Time.frameCount},我是哈基咩: {param1}");}private void Callback2(int param1, string param2){Debug.Log($"帧:{Time.frameCount},我是哈基咩: {param1} 我是咩咩 {param2}");}private void Progress(float param1){Debug.Log($"我是哈基咩: {param1}");}
}

 4.总结

         这是一次很好的体验 我从来没写过链式调用的代码 原来是这么一回事

        同时也做好了一个计时器以后就不用在每一个需要的地方进行update里面手搓辣

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TimeManager : MonoBehaviour
{private static TimeManager instance;public static TimeManager Instance => instance;// 链式调用的队列private Queue<IEnumerator> enumeratorQ = new Queue<IEnumerator>();private bool isChaining; // 是否正在执行队列private void Awake(){if (instance == null){instance = this;}}public TimeManager BeginChain(){enumeratorQ.Clear();return this;}/// <summary>/// 开始执行链式调用/// </summary>private void ExecuteChain(){if (!isChaining && enumeratorQ.Count > 0){StartCoroutine(RunChain());}}/// <summary>/// 出队跑/// </summary>/// <returns></returns>private IEnumerator RunChain(){isChaining = true;while (enumeratorQ.Count > 0){yield return StartCoroutine(enumeratorQ.Dequeue());}isChaining = false;}#region 检查合法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;}#endregion#region 等待固定时间秒public TimeManager WaitTime(float waitTime, Action callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitTimeHandle(waitTime, () => callback?.Invoke()));ExecuteChain();}return this;}public TimeManager WaitTime<T>(float waitTime, T param, Action<T> callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitTimeHandle(waitTime, () => callback?.Invoke(param)));ExecuteChain();}return this;}public TimeManager WaitTime<T, K>(float waitTime, T param1, K param2, Action<T, K> callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitTimeHandle(waitTime, () => callback?.Invoke(param1, param2)));ExecuteChain();}return this;}private IEnumerator WaitTimeHandle(float waitTime, Action action){yield return new WaitForSeconds(waitTime);action?.Invoke();}#endregion#region 等待固定时间秒(不受缩放影响)public TimeManager WaitRealTime(float waitTime, Action callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitRealTimeHandle(waitTime, () => callback?.Invoke()));ExecuteChain();}return this;}public TimeManager WaitRealTime<T>(float waitTime, T param, Action<T> callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitRealTimeHandle(waitTime, () => callback?.Invoke(param)));ExecuteChain();}return this;}public TimeManager WaitRealTime<T, K>(float waitTime, T param1, K param2, Action<T, K> callback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(WaitRealTimeHandle(waitTime, () => callback?.Invoke(param1, param2)));ExecuteChain();}return this;}private IEnumerator WaitRealTimeHandle(float waitTime, Action action){yield return new WaitForSecondsRealtime(waitTime);action?.Invoke();}#endregion#region 按固定时间间隔循环执行/// <summary>/// 按固定时间间隔循环执行/// </summary>/// <param name="spacing"></param>/// <param name="overNumber"></param>/// <param name="callback"></param>/// <returns></returns>public TimeManager LoopTime(float spacing, int overNumber, Action callback){if (CheckTime(spacing) && CheckCount(overNumber)){enumeratorQ.Enqueue(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke()));ExecuteChain();}return this;}public TimeManager LoopTime<T>(float spacing, int overNumber, T param, Action<T> callback){if (CheckTime(spacing) && CheckCount(overNumber)){enumeratorQ.Enqueue(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke(param)));ExecuteChain();}return this;}public TimeManager LoopTime<T, K>(float spacing, int overNumber, T param1, K param2, Action<T, K> callback){if (CheckTime(spacing) && CheckCount(overNumber)){enumeratorQ.Enqueue(LoopTimeHandle(spacing, overNumber, () => callback?.Invoke(param1, param2)));ExecuteChain();}return this;}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 等待固定帧执行一次/// <summary>/// 等待固定帧执行一次/// </summary>/// <param name="frameCount"></param>/// <param name="callback"></param>/// <returns></returns>public TimeManager WaitFrame(int frameCount, Action callback){if (CheckCount(frameCount)){enumeratorQ.Enqueue(WaitFrameHandle(frameCount, () => callback?.Invoke()));ExecuteChain();}return this;}public TimeManager WaitFrame<T>(int frameCount, T param, Action<T> callback){if (CheckCount(frameCount)){enumeratorQ.Enqueue(WaitFrameHandle(frameCount, () => callback?.Invoke(param)));ExecuteChain();}return this;}public TimeManager WaitFrame<T, K>(int frameCount, T param1, K param2, Action<T, K> callback){if (CheckCount(frameCount)){enumeratorQ.Enqueue(WaitFrameHandle(frameCount, () => callback?.Invoke(param1, param2)));ExecuteChain();}return this;}private IEnumerator WaitFrameHandle(int frameCount, Action action){for (int i = 0; i < frameCount; i++){yield return null;}action?.Invoke();}#endregion#region 进度反馈/// <summary>/// 进度反馈/// </summary>/// <param name="waitTime"></param>/// <param name="progressCallback"></param>/// <param name="completeCallback"></param>/// <returns></returns>public TimeManager WaitTimeWithProgress(float waitTime, Action<float> progressCallback, Action completeCallback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(ProgressTimer(waitTime, progressCallback, completeCallback));ExecuteChain();}return this;}public TimeManager WaitTimeWithProgress<T>(float waitTime, T param, Action<float, T> progressCallback, Action<T> completeCallback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(ProgressTimer(waitTime, param, progressCallback, completeCallback));ExecuteChain();}return this;}public TimeManager WaitTimeWithProgress<T, K>(float waitTime, T param1, K param2, Action<float, T, K> progressCallback, Action<T, K> completeCallback){if (CheckTime(waitTime)){enumeratorQ.Enqueue(ProgressTimer(waitTime, param1, param2, progressCallback, completeCallback));ExecuteChain();}return this;}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();}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);}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 等待当前帧结束执行回调/// <summary>/// 等待当前帧结束执行回调/// </summary>/// <param name="callback"></param>/// <returns></returns>public TimeManager WaitForEndOfFrame(Action callback){enumeratorQ.Enqueue(WaitForEndOfFrameHandle(callback));ExecuteChain();return this;}public TimeManager WaitForEndOfFrame<T>(T param, Action<T> callback){enumeratorQ.Enqueue(WaitForEndOfFrameHandle(param, callback));ExecuteChain();return this;}public TimeManager WaitForEndOfFrame<T, K>(T param1, K param2, Action<T, K> callback){enumeratorQ.Enqueue(WaitForEndOfFrameHandle(param1, param2, callback));ExecuteChain();return this;}private IEnumerator WaitForEndOfFrameHandle(Action callback){yield return new WaitForEndOfFrame();callback?.Invoke();}private IEnumerator WaitForEndOfFrameHandle<T>(T param, Action<T> callback){yield return new WaitForEndOfFrame();callback?.Invoke(param);}private IEnumerator WaitForEndOfFrameHandle<T, K>(T param1, K param2, Action<T, K> callback){yield return new WaitForEndOfFrame();callback?.Invoke(param1, param2);}#endregion#region 无限循环执行 /// <summary>/// 放在链式的最后!/// </summary>/// <param name="spacing"></param>/// <param name="callback"></param>/// <returns></returns>public TimeManager LoopForever(float spacing, Action callback){if (CheckTime(spacing)){enumeratorQ.Enqueue(LoopForeverHandle(spacing, () => callback?.Invoke()));ExecuteChain();}return this;}public TimeManager LoopForever<T>(float spacing, T param, Action<T> callback){if (CheckTime(spacing)){enumeratorQ.Enqueue(LoopForeverHandle(spacing, () => callback?.Invoke(param)));ExecuteChain();}return this;}public TimeManager LoopForever<T, K>(float spacing, T param1, K param2, Action<T, K> callback){if (CheckTime(spacing)){enumeratorQ.Enqueue(LoopForeverHandle(spacing, () => callback?.Invoke(param1, param2)));ExecuteChain();}return this;}private IEnumerator LoopForeverHandle(float spacing, Action action){while (true){yield return new WaitForSeconds(spacing);action?.Invoke();//如果前期链式调用的时候把它算进去 就会卡死掉if (enumeratorQ.Count > 0)yield break;}}#endregionpublic void Stop(IEnumerator func){StopCoroutine(func);//停止退队的时候要还一个新的回去 不然其仍在队列之中if (enumeratorQ.Contains(func)){var tempQueue = new Queue<IEnumerator>();while (enumeratorQ.Count > 0){IEnumerator item = enumeratorQ.Dequeue();if (item != func){tempQueue.Enqueue(item);}}enumeratorQ = tempQueue;}}public void StopAll(){StopAllCoroutines();enumeratorQ.Clear();isChaining = false;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/32890.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件解析漏洞靶场集锦详解

一、IIS解析漏洞 环境安装&#xff1a;windows2003iis6 1.目录解析 .asp文件夹中的任意文件都会被当做asp文件去执行 1.在iis6的网站根目录新建⼀个名为1.asp的文件 2. 在1.asp中新建⼀个jpg文件。内容为 <%now()%>asp代码 3.在外部浏览器中访问iis⽹站中的1.jpg 发现…

零售业务订单处理自动化:吉客云对接金蝶云星空

销售单对接销售出库_类型1零售业务_合并&#xff1a;吉客云奇门数据集成到金蝶云星空 在现代零售业务中&#xff0c;数据的高效流转和准确处理是企业运营的关键。本文将分享一个实际案例&#xff0c;展示如何通过轻易云数据集成平台&#xff0c;将吉客云奇门的数据无缝对接到金…

python-leetcode-子数组最大平均数 I

643. 子数组最大平均数 I - 力扣&#xff08;LeetCode&#xff09; 可以使用滑动窗口&#xff08;Sliding Window&#xff09;的方法来解决这个问题。具体步骤如下&#xff1a; 先计算数组 nums 中前 k 个元素的和 sum_k&#xff0c;作为初始窗口的和。然后滑动窗口&#xff0…

「 机器人 」扑翼飞行器通过总气动力控制四自由度运动方法

一、前言 在扑翼飞行中,总气动力(Total Aerodynamic Force)是指扑翼在运动过程中受到的所有空气动力作用的合力。它是由以下两种主要力的合成结果: 1. 升力(Lift, ):垂直于空气流方向的力,用于支持飞行器(或生物)的重量。 2. 阻力(Drag, ):平行于空气流方向的力,…

【C语言系列】字符函数和字符串函数

字符函数和字符串函数 一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2strlen函数模拟实现 四、strcpy的使用和模拟实现4.1strcpy函数4.2strcpy函数的模拟实现 五、strcat的使用和模拟实现5.1strcat函数5.2strcat函数的模拟实现 六、strcmp的使用…

飞鸟与鱼不同路

看&#xff0c;好美的太阳。 嘿嘿&#xff0c;今天我提出辞去综合教研室主任一职&#xff0c;不想在这个管理上废时间啦~ 把时间用来考试.........用来做自己的事情。 哈哈哈哈~

AI本地部署

文档加载&#xff08;Document Loading&#xff09;&#xff1a;从多种不同来源加载文档。LangChain提供了100多种不同的文档加载器&#xff0c;包括PDF在内的非结构化的数据、SQL在内的结构化的数据&#xff0c;以及Python、Java之类的代码等​ •文本分割&#xff08;Splitti…

计算机视觉算法实战——驾驶员分心检测(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​ 1. 领域简介&#xff1a;驾驶员分心检测的意义与挑战 驾驶员分心检测是智能驾驶安全领域的重要研究方向。据统计&#xff0c;全球每…

2025因果机器学习好中高区idea汇总

机器学习变天了&#xff01;近来因果机器学习大热&#xff0c;这便意味着机器学习已经从“预测”向“理解”的范式转变。同时&#xff0c;这也是我们发论文、找创新的好时机。 因果机器学习可谓是&#xff0c;提高模型决策科学性和可靠性的“仙丹”&#xff01;其核心就在于&a…

Linux笔记---文件系统硬件部分

1. 文件系统 文件系统是操作系统用于明确存储设备&#xff08;常见的是磁盘&#xff0c;也有基于NAND Flash的固态硬盘&#xff09;或分区上的文件的方法和数据结构&#xff0c;即在存储设备上组织文件的方法。 1.1 基本组成 索引节点&#xff08;inode&#xff09;&#xff…

AutoSar架构-----XCP模块与协议介绍

1、XCP 模块定义 XCP 一般要求如下图&#xff1a; XCP 导入的类型需要如下表这些头文件&#xff1a; 2、ETAS 工具配置 2.1、XcpGeneral 配置 3、XCP 协议 ASAM-MCD-1MC&#xff1a;ECU 和标定测量系统接口 ASAM-MCD-2MC&#xff1a;即 A2L 文件&#xff0c;是控制器内部信息…

江科大51单片机笔记【10】DS1302时钟可调时钟(下)

写在前言 此为博主自学江科大51单片机&#xff08;B站&#xff09;的笔记&#xff0c;方便后续重温知识 在后面的章节中&#xff0c;为了防止篇幅过长和易于查找&#xff0c;我把一个小节分成两部分来发&#xff0c;上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识…

字节流 InputStream/OutputStream

一、java的I/O java的I/O(输入/输出)流是用于处理数据输入和输出的抽象类。 java的I/O流主要分为两大类&#xff0c;字节流跟字符流。 字节流&#xff1a;用于处理二进制数据&#xff0c;包括InputStream和OutputStream两个主要类及其子类。 字符流&#xff1a;用于处理字符…

使用位运算如何找到数组中只出现一次的数?

题目链接&#xff1a;137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 算法解析 位运算是用于二进制的运算符号。而对于多次出现的数字&#xff0c;其二进制都是一模一样的&#xff0c;这里是3次重复的出现是数字。由此我们可以想到&#xff0c;如果我们由低…

最节省服务器,手搓电子证书查询系统

用户预算150元&#xff0c;想要一个最简单证书查询系统。前台能查询证书、后台管理员能登录能修改密码&#xff0c;证书能够手动输入修改删除、批量导入导出删除数据、查询搜索。能够兼容苹果、安卓、PC三端浏览器&#xff0c;最后帮忙部署到云服务器上。 用户预算不多&#xf…

.net 6程序在IIS中部署后点击IIS设置报错“执行此操作时出错”

.net 6写的程序&#xff0c;需要在Windows服务器的IIS中部署&#xff0c;由于是刚装的系统&#xff0c;先安装.net 6运行时&#xff0c;装了才发现没有IIS&#xff0c;于是又通过“添加角色和功能”添加与IIS相关的功能。安装完毕后&#xff0c;在IIS中添加网站&#xff0c;并将…

探针泄露(WEB)

##解题思路 题目提示是探针泄露&#xff0c;未及时删除的探针可能造成严重的数据泄露 探针的文件常见命名为tz.php&#xff0c;访问它 对于php相关参数&#xff0c;我们是可以点击的&#xff0c;点击phpinfo访问 跳转后搜索flag&#xff0c;得到flag

考研复试c语言常见问答题汇总2

11. 关键字和一般标识符有什么不同&#xff1f; C语言中关键字与一般标识符区别&#xff1a; 定义&#xff1a;关键字是C语言预定义的特殊单词&#xff08;如int、for&#xff09;&#xff0c;有固定含义&#xff1b;标识符是自定义的名称&#xff08;如变量名、函数名&#xf…

贝壳找房:以 OceanBase 为 JuiceFS 元数据引擎,构建 AI 存储底座

本文作者&#xff1a;王天庆&#xff0c;贝壳计算存储方向容器引擎团队负责人&#xff0c;他专注于云原生技术和AI基础设施的架构设计与实践&#xff0c;在为公司搭建高效、可靠的基础设施的同时&#xff0c;促进了大模型技术在企业内部的快速落地与应用。 导语&#xff1a;随着…

人工智能-周志华ML版|系列习题参考答案与综合测试目录

YI时间&#xff5c;松子茶碎碎念&#xff5c;MM-DFW&#xff5c;LAMBDA系列 星标&#x1f31f;松子茶 更新不掉队&#x1f31f; 作者 | 松子茶 © 原创内容(除图片外) 未经作者授权&#xff0c;严禁转载或镜像 机器学习是人工智能领域的核心课程之一。机器学习的基本概念…