【Unity3D日常开发】提高开发效率之定时器系统实现
推荐阅读
- 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日常开发】提高开发效率之定时器系统实现相关推荐
- 开发提高工作效率的开发工具和办公软件
最近一段时间比较迷恋好工具,俗话说,磨刀不误砍柴工,下面是浏览到的工具,其中百分之80都用过,而且经常用,自己没有时间整理,首先感谢原创的整理,下面中也有我做的些简单补充: eclipse(集成开发环 ...
- IDE+vim,提高开发效率
IdeaVim 提高开发效率 为什么要用IdeaVim? 解放上下左右键位,所有的键位都在主键盘: 自定义快捷键,快速定位: 解放鼠标 : 总之 :双手不离开键盘,快速开发 提高开发效率: 安装 ph ...
- 【吐血整理】【配图】提高开发效率的Window快捷键
了解一些常见快捷键,装逼的同时提高效率,快学起来吧! windos常用快捷键 1.快速选中光标之前文字:shift+end .这里的end键还可以单独使用,按下后光标跳到所在行的行尾. 2.快速选中 ...
- 如何利用“跑腿系统”来提高生活效率?
随着现代社会的快节奏发展,我们的生活越来越忙碌.为了更好地提高生活效率,跑腿系统应运而生.跑腿系统是一种通过网络平台或APP将需要跑腿服务的人与可提供服务的"跑腿员"联系起来,实现 ...
- SAP ABAP Development Tool 提高开发效率的十个小技巧
这是 Jerry 2021 年的第 46 篇文章,也是汪子熙公众号总共第 323 篇原创文章. Jerry 已经有很长一阵子没有打开工作电脑上的 SAP ABAP Development Tool 了 ...
- 如何通过组件化提高开发效率?
在软件开发过程中,大到业务模块的划分,小到技术组件的开发,都属于组件化的思考范畴内.很多时候我们到网上搜索「组件化」关键词,都只会看到关于前端组件化的资料,而对于后台开发组件化的资料却很少,那这是不是 ...
- Android开发: 分享利用好Kotlin的特点提高开发效率
Kotlin-first but not kotlin-must 谷歌在 I/O 大会上宣布,Kotlin 编程语言现在是 Android 应用程序开发人员的首选语言后,有更多的安卓程序投入Kotli ...
- Visual Studio 2017新版发布,极大提高开发效率丨附下载
2019独角兽企业重金招聘Python工程师标准>>> 最新的Visual Studio 2017免费下载[包含Professional.Enterprise.Community版本 ...
- EZ430 Chronos 如何提高开发调试效率探讨
2019独角兽企业重金招聘Python工程师标准>>> EZ430 Chronos 如何提高开发调试效率探讨 TI的 EZ430 Chronos 开发套件在调试程序时需要把手表拆开, ...
最新文章
- 第四周项目五-用递归方法求解(用递归求出两个数的最大公约数)
- 找出如下数组中最大的元素和最小的元素, a[][]={{3,2,6},{6,8,2,10},{5},{12,3,23}}
- dataframe 转rdd java,在pyspark中将RDD转换为Dataframe
- html游戏源妈简单,最简单的HTML5游戏——贪吃蛇
- c++17(26)-数组、二维数组的指针、指向数组的指针、指向数组的指针的指针
- red linux安装mysql_RedHat下安装MySQL5.5
- 快速傅里叶变换应用之二 hdu 4609 3-idiots
- kafka整合ldap权限管理
- Spring boot Rabbitmq 示例
- 【转】编辑器与IDE
- 输出毫秒_毫秒级网络监控(网络示波器)
- Android 银行账号
- 【Inpho精品教程】任务一:Inpho预处理准备(Pix4d生成未畸变图像、Pix4d生成相机参数文件)
- python打开360浏览器_python 模拟浏览器访问网页 selenium+chromedriver+360浏览器
- 计算机的常见故障及解决方法,最全的电脑开机常见故障及解决方法!
- 关于SQLite创建视图
- DHCP和域的概念知识
- 波士顿科学完成从霸菱亚洲收购科医人外科业务;刘孟元博士加盟克睿基因 | 医药健闻...
- 怎么给图片加滤镜?这三个实用方法教会你
- 云顶之弈怎么防止被机器人拉_云顶之奕机器人勾人规律和原理-云顶之奕机器人勾人技巧讲解...
热门文章
- oracle ora 16179,ora 06026 06023
- win10系统(64位)修复无法正常预览PDF内容的办法(非缩略图)
- 【知识点】了解之 纵深防御
- 小明和小强都是张老师的学生,张老师的生日是M月N日
- Android Permission denied 错误 ( 附Android权限大全 )
- server-u的详细设置
- CSDN上查看已关注的博客专栏
- 无源蜂鸣器按特定频率发出相对应的音调
- 可以测试妇科病的软件,判断一个女人有没有妇科病,都有哪些科学的检查方法?...
- 银行信用卡最低还款利息计算方法