目录

前言:

一、定义定时器

1、定义帧定时器类

2、定义普通定时器

二、定时器管理类


前言:

Unity游戏开发中需要定时器的原因主要有以下几点:

  1. 延迟操作:游戏中有很多需要在一定的时间间隔之后才能执行的操作。例如在某个角色死亡后需要重新生成、在物品被拾取后需要消失、在陷阱触发后需要一段时间再释放等等。此时就可以使用定时器来实现延迟操作,达到需要的效果。

  2. 倒计时:游戏中有很多需要倒计时的情况,例如任务倒计时、炸弹倒计时等。在这种情况下,我们可以使用定时器来记录时间并显示倒计时。当时间到达指定时间后,就可以执行相应的操作。

  3. 动画控制:在游戏中,一些动画需要精确的时间控制,例如闪烁、振动等。在这种情况下,定时器可以很好的帮助我们控制动画的播放时间和速度,使得动画可以按照我们的预期进行。

总之,定时器在Unity游戏开发中非常重要,可以帮助我们实现延迟操作、倒计时、精确的动画控制等功能。通过使用定时器,我们能够更加方便地控制游戏对象的行为和状态,从而提高游戏的玩家体验。

定时器是unity前端架构中必须有的一个模块功能。定时器一定要满足几个需求

第一、需要能够添加和删除定时器

第二、实现延时触发一次

第三、实现循环调用

第四、实现隔一定帧数调用一次


一、定义定时器

1、定义帧定时器类

帧定时器在希望某个操作在下一帧或一定帧数后执行,定时器接口中包含两个参数,定时器ID和object类型参数

Action<int, object> _action;

隔多少帧调用

_maxFrameCount 

完整的帧定时器代码如下:

 public class FrameTimer{private Action<int, object> _action;private int _maxFrameCount;private int _currentFrame;private object _param;public FrameTimer(Action<int, object> action, object param = null, int maxFrame = 1){_action = action;_maxFrameCount = maxFrame;_param = param;}public bool Execute(){try{if (_action != null)_action(0, _param);}catch (Exception e){ULog.Error(e);}return false;}public bool TryAction(){_currentFrame++;if (_currentFrame == _maxFrameCount)return true;return false;}}

2、定义普通定时器

如果是延时调用的一次定时器_intervalSeconds是延时时间

如果是循环(_isLoop)调用的定时器 _intervalSeconds,就是调用间隔时间

private float _intervalSeconds;
private bool _isLoop;

普通定时器类定义

 public class OneTimer{public Action<int,object> _action;private object _param;private float _intervalSeconds;private bool _isLoop;private float _beginTime;private int _id;public OneTimer(Action<int, object> action,float intervalSeconds,object param=null,bool isLoop=false){_id = UId.I.NextId();_action = action;_param = param;_isLoop = isLoop;_beginTime = TimeUtils.RealtimeSinceStartup;_intervalSeconds = intervalSeconds;}public void Execute(){try{if (_action != null)_action(_id, _param);}catch (Exception e){ULog.Error(e);}}public int Id{get { return _id; }}public float GetEndTime(){return _beginTime + _intervalSeconds;}public bool IsLoop{get { return _isLoop; }}public void UpdateNextTime(){_beginTime = GetEndTime();}public override string ToString(){StringBuilder sb = UString.GetBuilder();sb.Append(" id:" + _id);sb.Append(" ");if (_action != null){if (_action.Target != null){sb.Append(_action.Target.ToString());sb.Append(":");}if (_action.Method != null){sb.Append(_action.Method.ToString());}}sb.Append(" param:");sb.Append(_param);sb.Append(" intervalSeconds:");sb.Append(_intervalSeconds);sb.Append(" _isLoop:");sb.Append(_isLoop);sb.Append(" beginTime:");sb.Append(_beginTime);sb.Append(" waitSeconds:");sb.Append(GetEndTime() - TimeUtils.RealtimeSinceStartup);return sb.ToString();}}

二、定时器管理类

定时器定义每帧调用函数Update,_timers管理的是普通定时器,_frames管理的是帧定时器

UpdateFrameTimer循环遍历帧定时器是否符合触发条件,并进行触发

普通定时器隔一定时间判定一次,CHECK_INTERVAL_SECONDS来确定

 const float CHECK_INTERVAL_SECONDS = 0.1f;
 public class TimersComponent{const float CHECK_INTERVAL_SECONDS = 0.1f;private List<OneTimer> _timers = new List<OneTimer>();private List<OneTimer> _timersTemp = new List<OneTimer>();private float _NextCheckTime = 0.0f;private List<FrameTimer> _frames = new List<FrameTimer>();public int  AddLoop(Action<int,object> action, float intervalSeconds,object param=null){return Register(intervalSeconds, action, null, true);}public int AddOnce(Action<int, object> action, float beginSecond, object param){return Register(beginSecond, action, param);}public void  AddOnceDelayFrame(Action<int, object> action, object param=null,int delayFrameCount=1){_frames.Add(new FrameTimer(action,param, delayFrameCount));}private int Register(float intervalSeconds, Action<int, object> action, object param = null, bool isLoop  = false){if (action == null){LogError("Register: callback is null");return 0;}if (intervalSeconds <= 0.0f){LogError("Register: intervalSeconds = " + intervalSeconds + " <= 0.0f");return 0;}OneTimer data = new OneTimer(action, intervalSeconds, param, isLoop);_timers.Add(data);if (intervalSeconds < CHECK_INTERVAL_SECONDS){LogError("Register: Interval seconds: " + intervalSeconds + " < " + CHECK_INTERVAL_SECONDS);}if (_timers.Count >= 128){LogError("Register: Too many timers: " + _timers.Count + " >= 128. Please redesign TimerSimple");}return data.Id;}public bool Remove(int id){for (int i = 0; i < _timers.Count; ++i){if (_timers[i].Id == id){_timers.RemoveAt(i);return true;}}return false;}public bool Remove(Action<int, object> action){if (action == null){return false;}bool find = false;for (int i = 0; i < _timers.Count; ++i){if (_timers[i]._action == action){find = true;_timers.RemoveAt(i);--i;}}return find;}public void Update(){UpdateFrameTimer();float curTime = TimeUtils.RealtimeSinceStartup;if (curTime < _NextCheckTime){return;}if (_NextCheckTime <= 0.0f){_NextCheckTime = TimeUtils.RealtimeSinceStartup + CHECK_INTERVAL_SECONDS;return;}_NextCheckTime = curTime + CHECK_INTERVAL_SECONDS;_timersTemp.Clear();for (int i = 0; i < _timers.Count; ++i){OneTimer oneTimer = _timers[i];float endTime = oneTimer.GetEndTime();if (curTime >= endTime){_timersTemp.Add(oneTimer);if (!oneTimer.IsLoop){_timers.RemoveAt(i);--i;}}}for (int i = 0; i < _timersTemp.Count; ++i){OneTimer oneTimer = _timersTemp[i];oneTimer.Execute();oneTimer.UpdateNextTime();}_timersTemp.Clear();}private void UpdateFrameTimer(){for (int i = 0; i < _frames.Count; i++){FrameTimer timer = _frames[i];if (timer.TryAction()){timer.Execute();--i;_frames.RemoveAt(i);continue;}}}static void LogError(string str){Debug.LogError(TimeUtils.RealtimeSinceStartup + " TimerSimple." + str);}public void Destroy(){base.Destroy();_timersTemp.Clear();_timers.Clear();_frames.Clear();}}

当我们想要创建定时器时根据:循环定时器AddLoop、一次调用定时器AddOnce、一次调用帧定时器AddOnceDelayFrame接口创建我们想要的定时器。通过定时器id来Remove接口删除相应的定时器


unity前端架构之定时器完整代码实现相关推荐

  1. 前端架构设计1:代码核心

    现在的前端领域, 随着JS框架, UI框架和各种库的丰富, 前端架构也变得十分的重要. 如果一个大型项目没有合理的前端架构设计, 那么前端代码可能因为不同的开发人员随意的引入各种库和UI框架, 导致代 ...

  2. vue族谱架构_从零开始做Vue前端架构(1)

    前言 想想也已经做过不少架构的项目了,有基于vue,基于react,基于thinkPHP,基于laravel的. 做多了,也就对现有的架构有各种想法,有好的,有坏的,总之,用起来还是不爽.vue-cl ...

  3. 前端架构师神技,三招统一团队代码风格

    本文从代码规范,代码检查,代码格式化,以及编辑器自动化实现的方向,介绍代码规范统一在我们团队的实践应用. 大纲预览 本文介绍的内容包括以下方面: 认识代码规范 制定和统一规范 神技一:ESLint 神 ...

  4. 【Android 逆向】函数拦截 ( ARM 架构下的插桩拦截 | 完整代码示例 )

    文章目录 一.ARM 架构下的插桩拦截 二.完整代码示例 一.ARM 架构下的插桩拦截 ARM 架构下的跳转指令 : 下面的二进制数都是十六进制数 ; 323232 位指令 ; 04 F0 1F E5 ...

  5. unity 打砖块—休闲小游戏,摸鱼必备(完整代码)

    打砖块小游戏通常会被当做Unity学习的第一个案例,下面给大家介绍如何实现打砖块案例的 建立cube,大体这个样子,可以建造自己喜欢的形状和颜色. 给正方形的cube添加刚体 将摄像机的位置对准创建的 ...

  6. layui 实现问卷表单【页面数据渲染+答案提交】【前端完整代码】

    最近有个业务需求,需要做一个问卷表单 格式比较简单:问题+radio选项,问题需要分组展示,数据需要从数据库提取渲染. 细节较多 效果图如下 下面发一下前端完整代码(由于套用的是公司封装的layui框 ...

  7. js定时器,实现每天早上9点执行代码片段,完整代码

    js定时器,实现每天早上9点执行代码片段,完整代码 1.hour:小时,minute:分钟,callTask:函数 function setScheduledTask(hour, minute, ca ...

  8. 网页设计html最简单水印方法,前端canvas水印快速制作(附完整代码)

    两种水印效果如图: 原理解析: 图一斜纹类:创建一个和页面一样大的画布,根据页面大小以及倾斜角度大致铺满水印文字,最后转化为一张图片设为背景 图二倾斜类:将文字倾斜后转化为图片,然后设置背景图片rep ...

  9. 【手机号验证/前端】Vue2+elementUI编写一个手机号验证码登录页面,路由式开发(附完整代码)

    目录 效果图: 一.template部分 二.style样式 三.script部分 1.先对手机号的格式进行一个判断 2.接下来就是表单验证规则rules 3.最后就是methods了 (1)首先我们 ...

  10. 前端案例:像素鸟小游戏(js+dom操作,完整代码,附案例素材)

    目录 一.案例效果 二.实现思路 三.完整代码+详细注释 四.案例素材 一.案例效果 二.实现思路 创建游戏背景板和小鸟,并分别设置相对定位与绝对定位: 初始化背景图的位置: 初始化小鸟的位置: 设置 ...

最新文章

  1. 我敢打赌!你见过的所有程序员都是这样的!!!
  2. Android P 电量管理,Android P亮点汇总:更智能 更简单
  3. 如何使用RecyclerView构建Horizo​​ntal ListView?
  4. 以前的windows安装文件可以删除吗_安卓手机原来还可以这样安装windows系统,你还不知道吗?...
  5. 《leetcode》single-number-ii
  6. 8/7排位赛,codeforces501
  7. html生物代码,方舟生存进化生物代码 手游生物指令大全
  8. Himawari-8数据下载及命名
  9. PHP图片与文字合成
  10. div+css网页html成品学生作业包含10个html页面——动漫主题海贼王
  11. ABAP TRANSPORTING NO FIELDS 用法
  12. 解决Windows10 系统中桌面窗口管理器运行时占用内存过大的问题
  13. 工作11年,35岁,裸辞: 感到前途很迷茫,如何破?
  14. SQL 中的 COALESCE 函数初学者指南
  15. 洛谷P2738 [USACO4.1]篱笆回路Fence Loops(Floyed求最小环)
  16. elasticsearch部分常用操作
  17. Win10 Anaconda3安装
  18. 在服务器上一按l键自动退出,利用 SysRq 键排除和诊断系统故障
  19. linux541权限代表什么,linux中用户对文件的权限
  20. 单链表的Java简单实现

热门文章

  1. 织梦栏目加html,织梦dedecms调用栏目SEO标题,关键字,栏目描述的教程
  2. 让菜单充满活力:ASP.NET根据角色动态分配菜单+权限
  3. mysql 存数字_mysql 数据库varchar(100)可以存储多少个汉字,多少个数字
  4. .net的快递鸟物流单号自动识别查询api接口demo实例
  5. 【Hadoop-CosDistcp】通过CosDistcp的方式迁移Cos中的数据至HDFS
  6. 利用matlab附属的mtex将crc文件和cpr文件转化为ctf文件
  7. Tutorial教程:使用傅立叶变换检测图像边缘
  8. L10 安装网卡驱动
  9. TouchGFX开发(3)----使用TouchGFX配置IIC接口OLED
  10. 一段C++代码的一生(C++代码编译过程详解)