Unity 计时器工具类

原文链接

按照我的习惯进行修改

完整代码:

	/// 
    /// 计时器工具类
    /// 
    public class Timer : MonoBehaviour
    {
        public delegate void CompleteEvent();
        public delegate void UpdateEvent(float t);
        UpdateEvent updateEvent;
        CompleteEvent completedEvent;

        bool isEnableLog = true;        //是否打印消息
        bool isDestory = true;          //计时结束后是否销毁
        bool isDownNow = false;         //是否是倒计时
        bool isIgnoreTimeScale = true;  //是否忽略时间速率


        float timeTarget;   //目标时间
        float timeStart;    //开始计时时间
        float offsetTime;   //计时偏差

        bool isBegin;   //是否开始计时
        bool isEnd;     //计时是否结束
        bool isRepeate; //是否重复执行

        float now;      //正计时
        float downNow;  //倒计时

        public bool IsEnableLog
        {
            get { return isEnableLog; }
            set { isEnableLog = value; }
        }

        //是否使用游戏的真实时间 不依赖游戏的时间速度
        float TimeNow
        {
            get { return isIgnoreTimeScale ? Time.realtimeSinceStartup : Time.time; }
        }

        /// 
        /// 创建计时器
        /// 
        public static Timer CreateTimer(string name = "Timer")
        {
            GameObject go = new GameObject(name);
            Timer timer = go.AddComponent<Timer>();
            return timer;
        }

        /// 
        /// 设置参数,开始计时
        /// 
        /// 目标时间
        /// 完成回调函数
        /// 计时器进程回调函数
        /// 是否是倒计时
        /// 是否重复
        /// 是否忽略时间倍数
        /// 完成后是否销毁
        /// 是否开始
        public void StartTiming(float timeTarget, CompleteEvent onCompleted, UpdateEvent update = null,
            bool isDownNow = false, bool isRepeate = false, bool isIgnoreTimeScale = true, bool isDestory = true,
            float offsetTime = 0)
        {
            this.timeTarget = timeTarget;
            this.isIgnoreTimeScale = isIgnoreTimeScale;
            this.isRepeate = isRepeate;
            this.isDestory = isDestory;
            this.offsetTime = offsetTime;
            this.isDownNow = isDownNow;
            this.isBegin = true;
            this.isEnd = false;
            timeStart = TimeNow;

            if (onCompleted != null)
                completedEvent = onCompleted;
            if (update != null)
                updateEvent = update;
        }

        void Update()
        {
            if (isBegin)
            {
                now = TimeNow - offsetTime - timeStart;
                downNow = timeTarget - now;
                if (updateEvent != null)
                {
                    if (isDownNow)
                    {
                        updateEvent(downNow);
                    }
                    else
                    {
                        updateEvent(now);
                    }
                }
                if (now > timeTarget)
                {
                    if (completedEvent != null)
                        completedEvent();
                    if (!isRepeate)
                        Destory();
                    else
                        RestartTimer();
                }
            }
        }

        /// 
        /// 获取剩余时间
        /// 
        /// 
        public float GetTimeNow()
        {
            return Mathf.Clamp(timeTarget - now, 0, timeTarget);
        }

        /// 
        /// 计时结束
        /// 
        public void Destory()
        {
            isBegin = false;
            isEnd = true;
            if (isDestory)
            {
                Destroy(gameObject);
            }
        }

        float _pauseTime;
        /// 
        /// 暂停计时
        /// 
        public void PauseTimer()
        {
            if (isEnd)
            {
                if (isEnableLog) Debug.LogWarning("计时已经结束!");
            }
            else
            {
                if (isBegin)
                {
                    isBegin = false;
                    _pauseTime = TimeNow;
                }
            }
        }

        /// 
        /// 继续计时
        /// 
        public void ConnitueTimer()
        {
            if (isEnd)
            {
                if (isEnableLog) Debug.LogWarning("计时已经结束!请重新计时!");
            }
            else
            {
                if (!isBegin)
                {
                    offsetTime += (TimeNow - _pauseTime);
                    isBegin = true;
                }
            }
        }

        /// 
        /// 重新计时
        /// 
        public void RestartTimer()
        {
            timeStart = TimeNow;
            offsetTime = 0;
        }

        /// 
        /// 更改目标时间
        /// 
        /// 
        public void ChangeTargetTime(float time_)
        {
            timeTarget = time_;
            timeStart = TimeNow;
        }

        /// 
        /// 游戏暂停调用
        /// 
        /// 
        void OnApplicationPause(bool isPause_)
        {
            if (isPause_)
            {
                PauseTimer();
            }
            else
            {
                ConnitueTimer();
            }
        }
    }

工具更改:

using UnityEngine;

namespace MTools.Timer
{
    /// 
    /// 计时器工具类
    /// 
    public class Timer : MonoBehaviour
    {
        private System.Action completedEvent;
        private System.Action<float> progressEvent;

        private bool isDestory = true;          //计时结束后是否销毁
        private bool isDownNow = false;         //是否是倒计时
        private bool isIgnoreTimeScale = true;  //是否忽略时间速率


        private float timeTarget;   //目标时间
        private float timeStart;    //开始计时时间
        private float offsetTime;   //计时偏差

        private bool isBegin;   //是否开始计时
        private bool isEnd;     //计时是否结束
        private bool isRepeate; //是否重复执行

        private float now;      //正计时
        private float downNow;  //倒计时

        //是否使用游戏的真实时间 不依赖游戏的时间速度
        private float TimeNow
        {
            get { return isIgnoreTimeScale ? Time.realtimeSinceStartup : Time.time; }
        }

        /// 
        /// 创建计时器
        /// 
        /// 
        /// 计时任务完成是否销毁
        /// 是否倒计时
        /// 是否重复
        /// 是否忽略时间倍数
        /// 
        public static Timer CreateTimer(GameObject node, bool isDestory, bool isDownNow = false, bool isRepeate = false, bool isIgnoreTimeScale = true)
        {
            if (node == null) return null;

            Timer timer = node.GetComponent<Timer>();
            if (timer == null)
                timer = node.AddComponent<Timer>();
            timer.isDestory = isDestory;
            timer.isDownNow = isDownNow;
            timer.isRepeate = isRepeate;
            timer.isIgnoreTimeScale = isIgnoreTimeScale;
            return timer;
        }
        /// 
        /// 创建计时器
        /// 
        /// 
        /// 计时任务完成是否销毁
        /// 是否倒计时
        /// 是否重复
        /// 是否忽略时间倍数
        /// 
        public static Timer CreateTimer(Transform node, bool isDestory, bool isDownNow = false, bool isRepeate = false, bool isIgnoreTimeScale = true)
        {
            if (node == null) return null;

            Timer timer = node.gameObject.GetComponent<Timer>();
            if (timer == null)
                timer = node.gameObject.AddComponent<Timer>();
            timer.isDestory = isDestory;
            timer.isDownNow = isDownNow;
            timer.isRepeate = isRepeate;
            timer.isIgnoreTimeScale = isIgnoreTimeScale;
            return timer;
        }

        /// 
        /// 启动/开始计时
        /// 
        /// 目标时间
        /// 回调函数
        /// 计时偏差
        public void StartTimer(float timeTarget, System.Action onCompleted, float offsetTime = 0)
        {
            this.timeTarget = timeTarget;
            this.offsetTime = offsetTime;
            timeStart = TimeNow;

            if (onCompleted != null)
                completedEvent = onCompleted;

            isEnd = false;
            isBegin = true;
        }
        /// 
        /// 启动/开始计时
        /// 
        /// 目标时间
        /// 回调函数
        /// 进度回调函数
        /// 计时偏差
        public void StartTimer(float timeTarget, System.Action onCompleted, System.Action<float> onUpdateEvent, float offsetTime = 0)
        {
            this.timeTarget = timeTarget;
            this.offsetTime = offsetTime;
            timeStart = TimeNow;

            if (onCompleted != null)
                completedEvent = onCompleted;
            if (onUpdateEvent != null)
                progressEvent = onUpdateEvent;

            isEnd = false;
            isBegin = true;
        }

        /// 
        /// 重置计时器参数
        /// 
        /// 计时任务完成是否销毁
        /// 是否倒计时
        /// 是否重复
        /// 是否忽略时间倍数
        public void ResetOptions(bool isDestory, bool isDownNow = false, bool isRepeate = false, bool isIgnoreTimeScale = true)
        {
            completedEvent = null;
            progressEvent = null;

            this.isDestory = isDestory;
            this.isDownNow = isDownNow;
            this.isIgnoreTimeScale = isIgnoreTimeScale;

            timeTarget = 0f;
            timeStart = 0f;
            offsetTime = 0f;

            isBegin = false;
            isEnd = false;
            this.isRepeate = isRepeate;

            now = 0f;
            downNow = 0f;
        }

        void Update()
        {
            if (isBegin && !isEnd)
            {
                now = TimeNow - offsetTime - timeStart;
                downNow = timeTarget - now;
                if (isDownNow)
                {
                    progressEvent?.Invoke(downNow);
                }
                else
                {
                    progressEvent?.Invoke(now);
                }

                if (now > timeTarget)
                {
                    completedEvent?.Invoke();

                    if (isRepeate)
                    {
                        timeStart = TimeNow;
                        offsetTime = 0;
                    }
                    else
                    {
                        Destory();
                    }
                }
            }
        }

        /// 
        /// 获取剩余时间
        /// 
        /// 
        public float GetTimeNow()
        {
            return Mathf.Clamp(timeTarget - now, 0, timeTarget);
        }

        /// 
        /// 计时结束
        /// 
        public void Destory()
        {
            isBegin = false;
            isEnd = true;
            if (isDestory)
            {
                Destroy(this);
                Debug.Log("销毁了");
            }
        }

        float _pauseTime;
        /// 
        /// 暂停计时
        /// 
        public void PauseTimer()
        {
            if (isEnd)
            {
                Debug.LogWarning("计时已经结束!");
            }
            else
            {
                if (isBegin)
                {
                    isBegin = false;
                    _pauseTime = TimeNow;
                }
            }
        }

        /// 
        /// 继续计时
        /// 
        public void ConnitueTimer()
        {
            if (isEnd)
            {
                Debug.LogWarning("计时已经结束!请重新计时!");
            }
            else
            {
                if (!isBegin)
                {
                    offsetTime += (TimeNow - _pauseTime);
                    isBegin = true;
                }
            }
        }

        /// 
        /// 更改目标时间
        /// 
        /// 目标时间
        public void ChangeTargetTime(float timeTarget)
        {
            this.timeTarget = timeTarget;
            timeStart = TimeNow;
        }

        /// 
        /// 游戏暂停调用
        /// 
        /// 
        void OnApplicationPause(bool isPause_)
        {
            if (isPause_)
            {
                PauseTimer();
            }
            else
            {
                ConnitueTimer();
            }
        }
    }
}

测试代码

/*  $Header:   2022/12/07 星期三 下午 04:46:45    MTools    2020.2.6f1     $  */
/*******************************************************************************
 ***              C O N F I D E N T I A L  ---  M T O O L S                  ***
 *******************************************************************************
 *                                                                             *
 *                 Project Name : Test                                         *
 *                                                                             *
 *                    File Name : NewBehaviourScript.cs                        *
 *                                                                             *
 *                   Programmer : MTools                                       *
 *                                                                             *
 *                   Start Date : 2022/12/07 16:46:45                          *
 *                                                                             *
 *                  Last Update : 2022/12/07 16:46:45                          *
 *                                                                             *
 *-----------------------------------------------------------------------------*
 * Functions:                                                                  *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
using MTools;
using MTools.Timer;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace M
{
    public class NewBehaviourScript : MonoBehaviour
    {
        Timer timer = null;
        void Start()
        {
            //创建计时器
            timer = Timer.CreateTimer(gameObject, false);
            //启动计时器
            timer.StartTimer(1f, () => Debug.Log("任务重复执行"), (f) => Debug.Log($"进度: {f}"));
            //突然不想执行,执行另一个计时任务
            timer.ResetOptions(false);   //重置参数
            timer.StartTimer(2f, () => Debug.Log("新任务不重复执行"), (f) => Debug.Log($"新进度: {f}"));

            StartCoroutine(Stop());
        }

        private IEnumerator Stop()
        {
            Debug.Log("Stop");
            yield return new WaitForSeconds(5f);

            timer.ResetOptions(true, false, true);
            timer.StartTimer(3f, () => Debug.Log("新新任务重复执行"), (f) => Debug.Log($"新新进度: {f}"));
            Debug.Log("StopEnd");
        }
    }
}

如果要复用同一个Timer, 注意CreateTimer和ResetOptions中指定是否销毁(计时任务完成时)

你可能感兴趣的:(Unity工具,unity,游戏引擎)