推荐阅读

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

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

最近要实现个小功能:计时器。

计时器的用处很多,比如说在游戏开发中显示技能CD、buff持续时间、控制眩晕等状态的持续时间。

计时器的主要功能有:

  • 在规定时间内倒计时
  • 显示倒计时时间
  • 显示正计时时间
  • 暂停、继续
  • 时间速率影响
  • 获取倒计时剩余时间
  • 倒计时结束的回调

话说大树底下好乘凉,在有大佬的代码就是方便很多,找了一篇大佬写好的代码:
链接:unity计时器功能的实现

在实际使用中修改了一部分代码,将更加便捷使用,将修改后的代码分享给出来。

二、实现计时器

2-1、计时器实现

新建脚本,命名为Timer.cs:

using UnityEngine;public delegate void CompleteEvent();
public delegate void UpdateEvent(float t);public class Timer : MonoBehaviour
{UpdateEvent updateEvent;CompleteEvent onCompleted;bool isLog = true;//是否打印消息float timeTarget;   // 计时时间/float timeStart;    // 开始计时时间/float offsetTime;   // 计时偏差/bool isTimer;       // 是否开始计时/bool isDestory = true;     // 计时结束后是否销毁/bool isEnd;         // 计时是否结束/bool isIgnoreTimeScale = true;  // 是否忽略时间速率bool isRepeate;     //是否重复float now;          //当前时间 正计时float downNow;          //倒计时bool isDownNow = false;     //是否是倒计时// 是否使用游戏的真实时间 不依赖游戏的时间速度float TimeNow{get { return isIgnoreTimeScale ? Time.realtimeSinceStartup : Time.time; }}/// <summary>/// 创建计时器:名字  根据名字可以创建多个计时器对象/// </summary>public static Timer createTimer(string gobjName = "Timer"){GameObject g = new GameObject(gobjName);Timer timer = g.AddComponent<Timer>();return timer;}/// <summary>/// 开始计时/// </summary>/// <param name="time_">目标时间</param>/// <param name="isDownNow">是否是倒计时</param>/// <param name="onCompleted_">完成回调函数</param>/// <param name="update">计时器进程回调函数</param>/// <param name="isIgnoreTimeScale_">是否忽略时间倍数</param>/// <param name="isRepeate_">是否重复</param>/// <param name="isDestory_">完成后是否销毁</param>public void startTiming(float timeTarget, bool isDownNow = false,CompleteEvent onCompleted_ = null, UpdateEvent update = null,bool isIgnoreTimeScale = true, bool isRepeate = false, bool isDestory = true,float offsetTime = 0, bool isEnd = false, bool isTimer = true){this.timeTarget = timeTarget;this.isIgnoreTimeScale = isIgnoreTimeScale;this.isRepeate = isRepeate;this.isDestory = isDestory;this.offsetTime = offsetTime;this.isEnd = isEnd;this.isTimer = isTimer;this.isDownNow = isDownNow;timeStart = TimeNow;if (onCompleted_ != null)onCompleted = onCompleted_;if (update != null)updateEvent = update;}void Update(){if (isTimer){now = TimeNow - offsetTime - timeStart;downNow = timeTarget - now;if (updateEvent != null){if (isDownNow){updateEvent(downNow);}else{updateEvent(now);}}if (now > timeTarget){if (onCompleted != null)onCompleted();if (!isRepeate)destory();elsereStartTimer();}}}/// <summary>/// 获取剩余时间/// </summary>/// <returns></returns>public float GetTimeNow(){return Mathf.Clamp(timeTarget - now, 0, timeTarget);}/// <summary>/// 计时结束/// </summary>public void destory(){isTimer = false;isEnd = true;if (isDestory)Destroy(gameObject);}float _pauseTime;/// <summary>/// 暂停计时/// </summary>public void pauseTimer(){if (isEnd){if (isLog) Debug.LogWarning("计时已经结束!");}else{if (isTimer){isTimer = false;_pauseTime = TimeNow;}}}/// <summary>/// 继续计时/// </summary>public void connitueTimer(){if (isEnd){if (isLog) Debug.LogWarning("计时已经结束!请从新计时!");}else{if (!isTimer){offsetTime += (TimeNow - _pauseTime);isTimer = true;}}}/// <summary>/// 重新计时/// </summary>public void reStartTimer(){timeStart = TimeNow;offsetTime = 0;}/// <summary>/// 更改目标时间/// </summary>/// <param name="time_"></param>public void changeTargetTime(float time_){timeTarget = time_;timeStart = TimeNow;}/// <summary>/// 游戏暂停调用/// </summary>/// <param name="isPause_"></param>void OnApplicationPause(bool isPause_){if (isPause_){pauseTimer();}else{connitueTimer();}}
}

调用的计时器的脚本Test.cs:

using UnityEngine;
using System.Collections;
using System;public class Test : MonoBehaviour
{void Start(){// 创建计时器Timer timer = Timer.createTimer("GameTime");//开始计时timer.startTiming(10, true, OnComplete, OnProcess);}// 计时结束的回调void OnComplete(){Debug.Log("计时完成");}// 计时器的进程void OnProcess(float p){Debug.Log(FormatTime(p));}/// <summary>/// 格式化时间/// </summary>/// <param name="seconds">秒</param>/// <returns></returns>public static string FormatTime(float seconds){TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(seconds));string str = "";if (ts.Hours > 0){str = ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes > 0){str = ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes == 0){str = "00:" + ts.Seconds.ToString("00");}return str;}
}

2-2、测试倒计时

将Test.cs脚本附到场景中任意对象上,运行程序,测试倒计时:

3-3、测试正计时

修改代码,测试正计时:

 void Start()
{// 创建计时器Timer timer = Timer.createTimer("GameTime");//开始计时timer.startTiming(10, false, OnComplete, OnProcess);
}

运行结果:

3-4、测试获取剩余时间

修改代码:

using UnityEngine;
using System.Collections;
using System;public class Test : MonoBehaviour
{Timer timer;void Start(){// 创建计时器timer = Timer.createTimer("GameTime");//开始计时timer.startTiming(10, true);}void Update(){Debug.Log(timer.GetTimeNow());}
}

这次不使用回调函数,直接使用Update去获取剩余时间,运行结果:

3-5、测试暂停和继续

继续修改代码:

using UnityEngine;
using System.Collections;
using System;public class Test : MonoBehaviour
{Timer timer;void Start(){// 创建计时器timer = Timer.createTimer("GameTime");//开始计时timer.startTiming(10, true, OnComplete, OnProcess);}void Update(){if (Input.GetKeyDown(KeyCode.W)){Debug.Log("暂停");timer.pauseTimer();//暂停}if (Input.GetKeyDown(KeyCode.S)){Debug.Log("继续");timer.connitueTimer();//继续}if (Input.GetKeyDown(KeyCode.A)){Debug.Log("重新计时");timer.reStartTimer();//重新计时}if (Input.GetKeyDown(KeyCode.D)){Debug.Log("更改目标时间:20");timer.changeTargetTime(20);//更改目标时间}}// 计时结束的回调void OnComplete(){Debug.Log("计时完成");}// 计时器的进程void OnProcess(float p){Debug.Log(FormatTime(p));}/// <summary>/// 格式化时间/// </summary>/// <param name="seconds">秒</param>/// <returns></returns>public static string FormatTime(float seconds){TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(seconds));string str = "";if (ts.Hours > 0){str = ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes > 0){str = ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes == 0){str = "00:" + ts.Seconds.ToString("00");}return str;}
}   }return str;}
}

运行程序:

3-6、测试游戏加速

修改代码后:

using UnityEngine;
using System.Collections;
using System;public class Test : MonoBehaviour
{Timer timer;void Start(){Time.timeScale = 2;//游戏加速// 创建计时器timer = Timer.createTimer("GameTime");//开始计时timer.startTiming(60, true, OnComplete, OnProcess, false);}// 计时结束的回调void OnComplete(){Debug.Log("计时完成");}// 计时器的进程void OnProcess(float p){Debug.Log(FormatTime(p));}/// <summary>/// 格式化时间/// </summary>/// <param name="seconds">秒</param>/// <returns></returns>public static string FormatTime(float seconds){TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(seconds));string str = "";if (ts.Hours > 0){str = ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes > 0){str = ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");}if (ts.Hours == 0 && ts.Minutes == 0){str = "00:" + ts.Seconds.ToString("00");}return str;}
}

运行程序,不忽略游戏加速:

运行程序,忽略游戏加速:

三、后记

你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏 方向 简介
Unity3D开发小游戏 小游戏开发教程 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶 入门 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUI UGUI Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据 文件读取 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合 数据集合 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发 虚拟仿真 总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件 插件 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发 日常记录 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG 日常记录 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

【Unity3D日常开发】Unity3D中实现计时器工具类-正计时、倒计时、暂停计时、加速计时相关推荐

  1. Android 开发人员不得不收集的工具类集合

    RxTools 项目地址:vondear/RxTools  简介:Android 开发人员不得不收集的工具类集合 | 支付宝支付 | 微信支付(统一下单) | 微信分享 | Zip4j 压缩(支持分卷 ...

  2. Android项目中常用的工具类集(史上最全整理)

    如果你是一名有经验的Android开发者,那么你一定积累了不少的工具类,这些工具类是帮助我们快速开发的基础.如果你是新手,那么有了这些辅助类,可以让你的项目做起来更加的简单. 下面介绍一个在GitHu ...

  3. commons-lang3-3.2.jar中的常用工具类的使用

    这个包中的很多工具类可以简化我们的操作,在这里简单的研究其中的几个工具类的使用. 1.StringUtils工具类 可以判断是否是空串,是否为null,默认值设置等操作: /*** StringUti ...

  4. java编程中的断言工具类(org.springframework.util.Assert)

    转自:https://blog.csdn.net/gokeiryou263/article/details/19612471 断言工具类:Assert类, java.lang.Object ---&g ...

  5. Android中对话框的工具类

    Android中对话框的工具类,里面总结了比较好用的方法,直接调用即可 public class DialogUtils {private DialogUtils() {}private static ...

  6. Android快速开发不可或缺的11个工具类(下载)

    Android快速开发不可或缺的11个工具类(下载) 源码简介 Android快速开发不可或缺的11个辅助类,其中10个来自张鸿洋的博客,1个是我平时积攒的,复制粘贴到你的项目里,添加上包名就可以直接 ...

  7. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)

    文章目录 八.Java中的并发工具类 8.1 等待多线程完成的CountDownLatch 8.2 同步屏障CyclicBarrier 8.2.1 CyclicBarrier简介 8.2.2 Cycl ...

  8. 《Java并发编程的艺术》读后笔记-Java中的并发工具类(第八章)

    文章目录 <Java并发编程的艺术>读后笔记-Java中的并发工具类(第八章) 1.等待多线程完成的CountDownLatch 2.同步屏障CyclicBarrier 2.1 Cycli ...

  9. Android开发人员不得不收集的工具类集合

    一.Android开发人员不得不收集的工具类集合  ----收藏 https://github.com/RobertCow/RxTools 二.android 开发之listview工具集合框架 ht ...

最新文章

  1. Android之关于Intent的Flag属性的讲解
  2. 数据导出之sqlserver-导出脚本
  3. windows8专业版安装sql2012
  4. 安装了超图、oracle、eclipse、JDK后系统的java进程情况以及java.exe、javaw.exe
  5. wxWidgets:wxHtmlCellEvent类用法
  6. http 直接显示目录下文件_Linux文件管理(下)
  7. iOS-----线程同步与线程通信
  8. Hibernate查询 内连接和外连接区别
  9. 前端获取后端16位主键id,后3位四舍五入
  10. Luogu4114 Qtree1
  11. java sql 格式化_IDEA 格式化SQL代码技巧分享
  12. Spring5之IOC容器中IOC操作之Bean管理(二)之p名称空间注入、外部bean、内部bean、级联赋值
  13. 设置MAC地址和动态IP
  14. 11.8版本更新公告:灵罗娃娃 格温登场
  15. ssm:Unable to process Jar entry
  16. YOLOv5训练KAIST数据集
  17. LWN:5.17 合并窗口第一部分!
  18. 李俊“从良”碰壁,黑客的路有多长
  19. 未来计算机技术的发展趋势有哪些,从计算机的发展趋势来看,未来的计算机将会有哪些新技术?...
  20. Discuz如何开发移动端访客功能

热门文章

  1. 用Java爬虫爬取凤凰财经提供的沪深A股所有股票代号名称
  2. Docker 及 Docker Compose 安装及使用教程 (2020版)
  3. APISIX-Datadog 插件发布,助力用户提高系统的可观测性
  4. mac小技巧之打印文件
  5. 易基因 | DNA甲基化测序新技术发布:扩展重亚硫酸盐测序(XRBS)
  6. html页面在ie上不兼容,四招解决IE 11浏览器网页不兼容问题
  7. 关于微信录音的坑 amr格式音频文件HTML无法播放
  8. 使用Profiler进行性能分析
  9. 人活着最重要的是开心,理财最重要的是回本
  10. 【Python】多线程爬取某站高颜值小姐姐照片(共1.62GB)