推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客
  • QQ群:1040082875

一、前言

今天,来分享一下如何实现定时器。

实现定时器需要搞明白二个问题:

一、定时器如何实现
二、为什么制作定时器系统

首选,我们来了解一下如何在Unity里面实现定时器。

二、Unity 定时器的三种实现方法

在Unity开发程序的时候,会学习到很多实现定时器效果的方法,比如说:

2-1、使用Time.deltaTime累加方式

在Update里面,使用Time.deltaTime实现:

using UnityEngine;public class Test : MonoBehaviour
{public float timer = 0f; void Update(){timer += Time.deltaTime;if (timer >= 2){doSomething();timer = 0f; // 定时2秒}}void doSomething(){Debug.Log("每2秒执行一次");}
}

或者通过Time.time来实现:

using UnityEngine;public class Test : MonoBehaviour
{public float timer = 0f;void Start(){timer = Time.time;}void Update(){timer += Time.deltaTime;if (Time.time - timer >= 2)// 定时2秒{doSomething();timer = Time.time; }}void doSomething(){Debug.Log("每2秒执行一次");}
}

2-2、使用延迟调用函数

using UnityEngine;public class Test : MonoBehaviour
{void Start(){//0秒后,每2秒执行一次doSomethingInvokeRepeating("doSomething", 0, 2);}void doSomething(){Debug.Log("每2秒执行一次");}
}

2-3、使用协程

using System;
using System.Collections;
using UnityEngine;public class Test : MonoBehaviour
{void Start(){//每2秒执行一次doSomethingStartCoroutine(UpdateTimer(2f, doSomething));}void doSomething(){Debug.Log("每2秒执行一次");}IEnumerator UpdateTimer(float timer,Action callBack){var wait = new WaitForSeconds(timer);while (true){yield return wait;callBack();}}
}

提示:场景内协程多了将会出现明显的卡顿。

可以看出来,这三种实现定时器的方法都很简单,在项目体量不是太大,并且代码量也还算简洁的时候,使用这三种实现方法是没有问题的。

但是,当代码量多的时候,再使用这些方法就会显得冗余杂乱。

这时候就需要一个定时器系统来管理这些定时的任务,这就是为何要制作定时器系统的原因。

三、实现定时器系统

实现原理:

每个定时器对象是一个Timer, 添加的时候交给定时器管理系统, 定时器系统负责管理所有的定时器对象,每次游戏Update的时候,遍历里面的每个定时器对象,

把它们过去的时间增加Time.deltaTime, 当过去的时间达到定时器触发时间的时候,触发定时器调用, 如果达到Timer触发次数,就把这个Timer移除。

否则就重置时间,继续直到下一个时间的触发。

代码:

一个TimerMgr,Timer管理类,用来管理定时器系统:

using System.Collections.Generic;
using UnityEngine;class TimerNode
{public TimerMgr.TimerHandler callback;public float repeatRate; // 定时器触发的时间间隔;public float time; // 第一次触发要隔多少时间;public int repeat; // 你要触发的次数;public float passedTime; // 这个Timer过去的时间;public bool isRemoved; // 是否已经删除了public int timerId; // 标识这个timer的唯一Id号;
}public class TimerMgr
{public delegate void TimerHandler();private Dictionary<int, TimerNode> timers = null;//存放Timer对象private List<TimerNode> removeTimers = null;//新增Timer缓存队列private List<TimerNode> newAddTimers = null;//删除Timer缓存队列private int autoIncId = 1;//每个Timer的唯一标示//初始化Timer管理器public void Init(){timers = new Dictionary<int, TimerNode>();autoIncId = 1;removeTimers = new List<TimerNode>();newAddTimers = new List<TimerNode>();}/// <summary>/// 以秒为单位调用方法methodName,然后在每个repeatRate重复调用。/// </summary>/// <param name="methodName">回调函数</param>/// <param name="time">延迟调用</param>/// <param name="repeatRate">时间间隔</param>/// <param name="repeat">重复调用的次数 小于等于0表示无限触发</param>public int Schedule(TimerHandler methodName, float time, float repeatRate, int repeat=0){TimerNode timer = new TimerNode();timer.callback = methodName;timer.repeat = repeat;timer.repeatRate = repeatRate;timer.time = time;timer.passedTime = timer.repeatRate; // 延迟调用timer.isRemoved = false;timer.timerId = autoIncId;autoIncId++;newAddTimers.Add(timer); // 加到缓存队列里面return timer.timerId;}//移除Timerspublic void Unschedule(int timerId){if (!timers.ContainsKey(timerId)){return;}TimerNode timer = timers[timerId];timer.isRemoved = true; // 先标记,不直接删除}//在Update里面调用public void Update(){float dt = Time.deltaTime;// 添加新的Timersfor (int i = 0; i < newAddTimers.Count; i++){timers.Add(newAddTimers[i].timerId, newAddTimers[i]);}newAddTimers.Clear();foreach (TimerNode timer in timers.Values){if (timer.isRemoved){removeTimers.Add(timer);continue;}timer.passedTime += dt;if (timer.passedTime >= (timer.time + timer.repeatRate)){// 做一次触发timer.callback();timer.repeat--;timer.passedTime -= (timer.time + timer.repeatRate);timer.time = 0; if (timer.repeat == 0){// 触发次数结束,将该删除的加入队列timer.isRemoved = true;removeTimers.Add(timer);}}}// 清理掉要删除的Timer;for (int i = 0; i < removeTimers.Count; i++){timers.Remove(removeTimers[i].timerId);}removeTimers.Clear();}
}

调用:

using System;
using System.Collections;
using UnityEngine;public class Test : MonoBehaviour
{TimerMgr timer;int TimerID;void Start(){//初始化timer = new TimerMgr();timer.Init();//启动定时器TimerID = timer.Schedule(doSomething, 0, 2);}void Update(){timer.Update();if (Input.GetKeyDown(KeyCode.W)){//关闭定时器timer.Unschedule(TimerID);}}private void doSomething(){Debug.Log("每2秒执行一次");}
}

四、后言

这个定时器系统,可以用来处理在开发中可能用到的定时器需求。

不用再去Time.deltatime或者用协程去制作定时器了。

制作完定时器后,在其他项目也可以使用。

【Unity3D日常开发】提高开发效率之定时器系统实现相关推荐

  1. 开发提高工作效率的开发工具和办公软件

    最近一段时间比较迷恋好工具,俗话说,磨刀不误砍柴工,下面是浏览到的工具,其中百分之80都用过,而且经常用,自己没有时间整理,首先感谢原创的整理,下面中也有我做的些简单补充: eclipse(集成开发环 ...

  2. IDE+vim,提高开发效率

    IdeaVim 提高开发效率 为什么要用IdeaVim? 解放上下左右键位,所有的键位都在主键盘: 自定义快捷键,快速定位: 解放鼠标 : 总之 :双手不离开键盘,快速开发 提高开发效率: 安装 ph ...

  3. 【吐血整理】【配图】提高开发效率的Window快捷键

    了解一些常见快捷键,装逼的同时提高效率,快学起来吧! windos常用快捷键 1.快速选中光标之前文字:shift+end  .这里的end键还可以单独使用,按下后光标跳到所在行的行尾. 2.快速选中 ...

  4. 如何利用“跑腿系统”来提高生活效率?

    随着现代社会的快节奏发展,我们的生活越来越忙碌.为了更好地提高生活效率,跑腿系统应运而生.跑腿系统是一种通过网络平台或APP将需要跑腿服务的人与可提供服务的"跑腿员"联系起来,实现 ...

  5. SAP ABAP Development Tool 提高开发效率的十个小技巧

    这是 Jerry 2021 年的第 46 篇文章,也是汪子熙公众号总共第 323 篇原创文章. Jerry 已经有很长一阵子没有打开工作电脑上的 SAP ABAP Development Tool 了 ...

  6. 如何通过组件化提高开发效率?

    在软件开发过程中,大到业务模块的划分,小到技术组件的开发,都属于组件化的思考范畴内.很多时候我们到网上搜索「组件化」关键词,都只会看到关于前端组件化的资料,而对于后台开发组件化的资料却很少,那这是不是 ...

  7. Android开发: 分享利用好Kotlin的特点提高开发效率

    Kotlin-first but not kotlin-must 谷歌在 I/O 大会上宣布,Kotlin 编程语言现在是 Android 应用程序开发人员的首选语言后,有更多的安卓程序投入Kotli ...

  8. Visual Studio 2017新版发布,极大提高开发效率丨附下载

    2019独角兽企业重金招聘Python工程师标准>>> 最新的Visual Studio 2017免费下载[包含Professional.Enterprise.Community版本 ...

  9. EZ430 Chronos 如何提高开发调试效率探讨

    2019独角兽企业重金招聘Python工程师标准>>> EZ430 Chronos 如何提高开发调试效率探讨 TI的 EZ430 Chronos 开发套件在调试程序时需要把手表拆开, ...

最新文章

  1. 第四周项目五-用递归方法求解(用递归求出两个数的最大公约数)
  2. 找出如下数组中最大的元素和最小的元素, a[][]={{3,2,6},{6,8,2,10},{5},{12,3,23}}
  3. dataframe 转rdd java,在pyspark中将RDD转换为Dataframe
  4. html游戏源妈简单,最简单的HTML5游戏——贪吃蛇
  5. c++17(26)-数组、二维数组的指针、指向数组的指针、指向数组的指针的指针
  6. red linux安装mysql_RedHat下安装MySQL5.5
  7. 快速傅里叶变换应用之二 hdu 4609 3-idiots
  8. kafka整合ldap权限管理
  9. Spring boot Rabbitmq 示例
  10. 【转】编辑器与IDE
  11. 输出毫秒_毫秒级网络监控(网络示波器)
  12. Android 银行账号
  13. 【Inpho精品教程】任务一:Inpho预处理准备(Pix4d生成未畸变图像、Pix4d生成相机参数文件)
  14. python打开360浏览器_python 模拟浏览器访问网页 selenium+chromedriver+360浏览器
  15. 计算机的常见故障及解决方法,最全的电脑开机常见故障及解决方法!
  16. 关于SQLite创建视图
  17. DHCP和域的概念知识
  18. 波士顿科学完成从霸菱亚洲收购科医人外科业务;刘孟元博士加盟克睿基因 | 医药健闻...
  19. 怎么给图片加滤镜?这三个实用方法教会你
  20. 云顶之弈怎么防止被机器人拉_云顶之奕机器人勾人规律和原理-云顶之奕机器人勾人技巧讲解...

热门文章

  1. oracle ora 16179,ora 06026 06023
  2. win10系统(64位)修复无法正常预览PDF内容的办法(非缩略图)
  3. 【知识点】了解之 纵深防御
  4. 小明和小强都是张老师的学生,张老师的生日是M月N日
  5. Android Permission denied 错误 ( 附Android权限大全 )
  6. server-u的详细设置
  7. CSDN上查看已关注的博客专栏
  8. 无源蜂鸣器按特定频率发出相对应的音调
  9. 可以测试妇科病的软件,判断一个女人有没有妇科病,都有哪些科学的检查方法?...
  10. 银行信用卡最低还款利息计算方法