Unity简单计时器,实现随时播放,暂停,继续,停止

最近的项目中要用到简单的计时功能,又因为函数的构造已经写好了,不想去改变,所以最后用了dotween模拟计时功能,闲下来时就自己实现了一个简易的计时器

首先是状态图


计时器由三个状态组成,停止状态,播放状态和暂停状态,其中的切换逻辑见图

因为是一个工具类,所有为了使用上尽可能的简单,我在调用方式上模仿了dotween的使用方式

大致是这样的

 CountTimeModel model1;
    void Start () {
        //计时5秒
        model1 = CountTime.Count(5)
        .OnBegin(delegate
        {
            Debug.Log("开始");
        })
        .OnEnd(delegate {
            Debug.Log("结束");
        })
        .OnStop(delegate {
            Debug.Log("停止");
        })
        //更新,可以指定更新频率
        .OnUpdate(onTimeUpdate);

        model1.Begin();
        model1.Pause();
        model1.Continue();
        model1.Stop();
    }
    // update对应的回调需要有一个float参数
    void onTimeUpdate(float time)
    {
        Debug.Log(time);
    }

首先定义一个CountTimeModel对象,局部和全局的都可以,如果想在任意地方去暂停播放最好用全局类型

pause函数可以暂停计时,continue可以从之前的进度重新开始,这两个函数特别好用

内部实现原理,我使用了unity的协程机制,但是因为工具类没有继承自monobehaviour,所有在启动协程上使用了取巧的方式

/// <summary>
    /// 调用携程,需要借助这个类
    /// </summary>
    public class CountTimeGameObject : MonoBehaviour
    {
        public static void PrintT(string msg) {
            Debug.Log(msg);
        }
    }
在第一次计时时会创建一个空的对象去挂载这个脚本,然后将这个实例的引用抓在手里,后面全部通过这个behaviour的子类去启动协程

最开始的方法是在begin时需要将调用者传入以执行协程,后面觉得不够方便,违反了工具类的实质,而且不是所有的调用者都继承了monobehaviour

/// <summary>
    /// 更新频率,执行update的频率
    /// </summary>
    public enum UpdateLevel
    {
        S,//1秒
        S0,//0.1秒
        S00//0.01秒
    }

    /// <summary>
    /// 计时器的三种状态
    /// </summary>
    public enum CountTimeStateType{
        STOPED,
        PLAYING,
        PAUSED
    }

    /// <summary>
    /// 操作类型
    /// </summary>
    public enum OperationType {
        NORMAL,//正常类型
        PAUSED,//暂停操作
        STOP//停止操作
    }
在创建计时实例时可以指定update刷新的类型,是通过 UpdateLevel类型实现的,控制每多久执行一个update回调

其他两个类型用来控制状态的切换

最后是全部的代码,如果在使用过程中发现有什么问题或者需要改进,添加的功能都可以留言告诉我,我自己也在用这个脚本,慢慢优化

// ========================================================
// 描 述:计时工具类
// 作 者:xzf 
// 创建时间:2017/11/14 15:36:35
// 版 本:v 1.0
// ========================================================
using System;
using System.Collections;
using UnityEngine;

namespace StoneTools
{
    /// <summary>
    /// 对CountTimeModel的调用做一层封装,添加了一些处理
    /// </summary>
    public class CountTime
    {
        public static CountTimeGameObject CountTimeObject;

        /// <summary>
        /// 计时
        /// </summary>
        /// <param name="time">时间</param>
        /// <returns></returns>
        public static CountTimeModel Count(float time)
        {
            if (!checkTimeAvailable(time)) {
                return null;
            }
            checkCountTimeObject();
            CountTimeModel timeModel = new CountTimeModel(time);
            return timeModel;
        }

        /// <summary>
        /// 计时
        /// </summary>
        /// <param name="time">时间</param>
        /// <param name="level">刷新频率(调用update),默认为0.1s</param>
        /// <returns></returns>
        public static CountTimeModel Count(float time, UpdateLevel level)
        {
            if (!checkTimeAvailable(time))
            {
                return null;
            }
            checkCountTimeObject();
            CountTimeModel timeModel = new CountTimeModel(time, level);
            return timeModel;
        }

        /// <summary>
        /// 计时
        /// </summary>
        /// <param name="time">时间</param>
        /// <param name="isRealTime">是否真实时间,默认为游戏中时间</param>
        /// <returns></returns>
        public static CountTimeModel Count(float time, bool isRealTime)
        {
            if (!checkTimeAvailable(time))
            {
                return null;
            }
            checkCountTimeObject();
            CountTimeModel timeModel = new CountTimeModel(time, isRealTime);
            return timeModel;
        }

        /// <summary>
        /// 计时
        /// </summary>
        /// <param name="time">时间</param>
        /// <param name="level">刷新频率(调用update),默认为0.1s</param>
        /// <param name="isRealTime">是否真实时间,默认为游戏中时间</param>
        /// <returns></returns>
        public static CountTimeModel Count(float time, UpdateLevel level, bool isRealTime)
        {
            if (!checkTimeAvailable(time))
            {
                return null;
            }
            checkCountTimeObject();
            CountTimeModel timeModel = new CountTimeModel(time, isRealTime);
            return timeModel;
        }

        static void checkCountTimeObject()
        {
            if (CountTimeObject == null)
            {
                GameObject tGO = new GameObject("【CountTimeObject】");
                CountTimeObject = tGO.AddComponent<CountTimeGameObject>();
            }
        }

        static bool checkTimeAvailable(float time) {
            if (time <= 0)
                return false;
            return true;
        }
    }

    /// <summary>
    /// 调用携程,需要借助这个类
    /// </summary>
    public class CountTimeGameObject : MonoBehaviour
    {
        public static void PrintT(string msg) {
            Debug.Log(msg);
        }
    }

    /// <summary>
    /// 更新频率,执行update的频率
    /// </summary>
    public enum UpdateLevel
    {
        S,//1秒
        S0,//0.1秒
        S00//0.01秒
    }

    /// <summary>
    /// 计时器的三种状态
    /// </summary>
    public enum CountTimeStateType{
        STOPED,
        PLAYING,
        PAUSED
    }

    /// <summary>
    /// 操作类型
    /// </summary>
    public enum OperationType {
        NORMAL,//正常类型
        PAUSED,//暂停操作
        STOP//停止操作
    }

    public class CountTimeModel
    {
        private float _aimTime;
        private float _currentTime = 0;
        private float _updateValue = 0.1f;
        private bool _isRealTime = false;

        Action _beginAction;        //开始
        Action<float> _updateAction;//更新
        Action _endAction;          //正常结束
        Action _stopAction;         //中途停止

        //记录当前状态
        private CountTimeStateType _state = CountTimeStateType.STOPED;
        //记录上一步执行的操作
        private OperationType _operation = OperationType.NORMAL;

        public CountTimeModel(float cTime)
        {
            _aimTime = cTime;
        }

        public CountTimeModel(float cTime, bool isRealTime)
        {
            _aimTime = cTime;
            _isRealTime = isRealTime;
        }

        public CountTimeModel(float cTime, UpdateLevel level)
        {
            _aimTime = cTime;
            setUpdateLevel(level);
        }

        public CountTimeModel(float cTime, UpdateLevel level, bool isRealTime) {
            _aimTime = cTime;
            setUpdateLevel(level);
            _isRealTime = isRealTime;
        }

        void setUpdateLevel(UpdateLevel level) {
            switch (level)
            {
                case UpdateLevel.S:
                    _updateValue = 1f;
                    break;
                case UpdateLevel.S0:
                    _updateValue = 0.1f;
                    break;
                case UpdateLevel.S00:
                    _updateValue = 0.01f;
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 开始
        /// </summary>
        public void Begin()
        {
            if (_state != CountTimeStateType.STOPED)
                return;
            if (_beginAction != null)
            {
                _beginAction();
            }
            _currentTime = 0;
            CountTime.CountTimeObject.StartCoroutine(updateTime());
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause() {
            if (_state != CountTimeStateType.PLAYING)
                return;
            _operation = OperationType.PAUSED;
        }

        /// <summary>
        /// 继续
        /// </summary>
        public void Continue() {
            if (_state != CountTimeStateType.PAUSED)
                return;
            _operation = OperationType.NORMAL;
            CountTime.CountTimeObject.StartCoroutine(updateTime());
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop() {
            if (_state == CountTimeStateType.STOPED)
                return;
            _operation = OperationType.STOP;
        }

        IEnumerator updateTime()
        {
            _state = CountTimeStateType.PLAYING;
            if (_isRealTime)
            {
                while (_currentTime < _aimTime)
                {
                    //停止计时
                    if (_operation != OperationType.NORMAL)
                        break;
                    yield return new WaitForSecondsRealtime(_updateValue);
                    _currentTime += _updateValue;
                    if(_updateAction != null)
                        _updateAction(_currentTime);
                }
            }
            else
            {
                while (_currentTime < _aimTime)
                {
                    //停止计时
                    if (_operation != OperationType.NORMAL)
                        break;
                    yield return new WaitForSeconds(_updateValue);
                    _currentTime += _updateValue;
                    if (_updateAction != null)
                        _updateAction(_currentTime);
                }
            }
            if (_operation == OperationType.STOP)
            {
                if (_stopAction != null)
                    _stopAction();
                _state = CountTimeStateType.STOPED;
            }
            else if (_operation == OperationType.NORMAL)
            {
                if (_endAction != null)
                    _endAction();
                _state = CountTimeStateType.STOPED;
            }
            else if (_operation == OperationType.PAUSED) {
                _state = CountTimeStateType.PAUSED;
            }
            _operation = OperationType.NORMAL;
            yield return 0;
        }

        public CountTimeModel OnBegin(Action ac)
        {
            _beginAction = ac;
            return this;
        }

        public CountTimeModel OnUpdate(Action<float> ac)
        {
            _updateAction = ac;
            return this;
        }

        public CountTimeModel OnEnd(Action ac)
        {
            _endAction = ac;
            return this;
        }

        public CountTimeModel OnStop(Action ac) {
            _stopAction = ac;
            return this;
        }
    }
}





  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值