Unity 封装一个依赖于MonoBehaviour的计时器(上) 基本功能

devtools/2025/3/16 16:50:00/

        灵感来自下面这本书的协程部分,因此我就自己尝试写了一个

       我的新书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来替代,但是可能涉及到了多线程,我这块学了但是用的不多还需加强


http://www.ppmy.cn/devtools/167605.html

相关文章

如何在github上参与开源项目

1. 创建 GitHub 账号 如果你还没有 GitHub 账号&#xff0c;首先需要注册一个&#xff1a; 访问 GitHub 官网。 点击右上角的“Sign up”按钮&#xff0c;填写注册信息并完成注册。 2. 找到感兴趣的项目 GitHub 上有成千上万的开源项目&#xff0c;你可以通过以下方式找到感兴趣…

prototype和proto的区别

在 JavaScript 中&#xff0c;prototype 和 __proto__ 都与原型链和继承机制有关&#xff0c;但它们的含义和作用是不同的。下面来详细讲解它们的区别。 一、prototype 和 proto 的区别 特性prototype__proto__作用构造函数的原型对象实例对象的隐式原型类型对象对象访问方式构…

数据库管理-第302期 国产类RAC架构数据库网络连接方式(20250314)

数据库管理302期 2025-03-14 数据库管理-第302期 国产类RAC架构数据库网络连接方式&#xff08;20250314&#xff09;1 Oracle RAC2 DMDSC3 YAC4 KES RAC总结 数据库管理-第302期 国产类RAC架构数据库网络连接方式&#xff08;20250314&#xff09; 作者&#xff1a;胖头鱼的鱼…

封装WPF中转换器常用用法封装

代码经常遇到类型A转换到类型C&#xff0c;但是已经写好类型A转换到类型B、类型B转换类型C。往往遇到这种情况&#xff0c;通常会重新写过一个转换器来进行满足需求。以下是解决该痛点。 /// <summary> /// 转换器组转换器 /// </summary> [ContentProperty(nameo…

【前端实战】一文掌握响应式布局 - 多设备完美适配方案详解

一、前言 在当今互联网时代&#xff0c;用户通过各种设备访问网站已成为常态。如何让网站在不同设备上都能完美展现&#xff1f;本文将通过一个实际案例&#xff0c;详细讲解响应式布局的实现方案。 二、项目效果展示 PC 移动端 平板(ipad Pro) 三、核心实现方案 1. 基础设置…

《DeepSeek 开源 DeepGEMM:开启AI计算新时代的密钥》:此文为AI自动生成

《DeepSeek 开源 DeepGEMM&#xff1a;开启AI计算新时代的密钥》&#xff1a;此文为AI自动生成 引言&#xff1a;AI 计算的新曙光 在当今科技飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最为耀眼的领域之一。从语音助手到自动驾驶&#xff0c;从图像…

基于Spring Boot的航司互售系统

文章目录 项目介绍项目截图项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &#x1f345;文末获取源码联系&#x1f34…

使用WireShark解密https流量

概述 https协议是在http协议的基础上&#xff0c;使用TLS协议对http数据进行了加密&#xff0c;使得网络通信更加安全。一般情况下&#xff0c;使用WireShark抓取的https流量&#xff0c;数据都是加密的&#xff0c;无法直接查看。但是可以通过以下两种方法&#xff0c;解密抓…