计时器封装

 心血来潮写个计时器玩一下

在开发的过程中难免会遇到需要大量的计时器,有一个好的计时器对开发或者程序的运行效率都有很大的提升

作为一个合格的程序员,我们不可能每次有计时都在update去做一个计时或者新开一个协程去计时,太麻烦辣,效率太慢辣,性能还差

所以赶紧封装器来...

 

这个计时器的思路是对需要计时的任务全部存起来,并按照时间的排序插入到一个时间顺序对应的节点,那么只需要有一个计时就可以把所有计时任务统一处理掉

因为插入移除的修改比较频繁,所有用了链表去对各个任务节点做的一个连接

真正在项目里使用的时候还是需要根据实际使用情况来封装的

 

生命在于成长,如果我的思路有问题可以提出来,谢谢,但不接受喷子,嘿嘿

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//计时节点
public class TimerCon
{
    public float _waitTime;
    public float waitTime;      // 等待时间
    public Action action;        // 执行事件
    public int loopNum;         // 循环次数  0 不循环 -1无限循环  >1指定次数
}

public class TimerConManager : UnitySlingleton<TimerConManager>  //单例类 处理
{
    private float timer = 0f;           // 当前计时器时间      累计时长  可扩展重置
    private bool isActive = true;      // 是否激活计时器
    LinkedList<TimerCon> nodeList = new LinkedList<TimerCon>();       //节点链表 排序存储计时事件
    private Coroutine coroutine;              //协程任务

    /// <summary>
    /// 开始计时 外部调用
    /// </summary>
    public void StartTimeDown(float waitTime, Action action, int loopNum = 0)
    {
        TimerCon node = new TimerCon();
        node._waitTime = waitTime;
        node.waitTime = waitTime + timer;
        node.action = action;
        node.loopNum = loopNum;

        InsterNode(node);
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Runtime());
        }
    }

    /// <summary>
    /// 关闭计时 外部调用
    /// </summary>
    public void RemoveNode(TimerCon node)
    {
        if (nodeList.Find(node) != null)
        {
            nodeList.Remove(node);
        }
    }

    //插入计时节点  
    private void InsterNode(TimerCon node)
    {
        bool isFirstNodeTimeDown = false;   //首节点
        if (nodeList.Count == 0)
        {
            nodeList.AddLast(node);
        }
        else
        {
            LinkedListNode<TimerCon> previousNode = GetNodePoint(node.waitTime);
            isFirstNodeTimeDown = previousNode == nodeList.First;

            if (isFirstNodeTimeDown)
            {
                nodeList.AddBefore(previousNode, node);
            }
            else
            {
                nodeList.AddAfter(previousNode, node);
            }

        }
    }

    //计算节点位置
    private LinkedListNode<TimerCon> GetNodePoint(float waitTime, LinkedListNode<TimerCon> curNode = null)
    {
        if (nodeList.Count == 0)
        {
            return null;
        }
        if (curNode == null)
        {
            curNode = nodeList.First;
        }
        //首节点 需特殊处理
        if (waitTime <= curNode.Value.waitTime)
        {
            return curNode;
        }
        if (curNode.Next != null && curNode.Next.Value.waitTime <= waitTime)
        {
            return GetNodePoint(waitTime, curNode.Next);
        }
        return curNode;
    }

    //一直在计时的协程 暂定 
    private IEnumerator Runtime()
    {
        while (isActive)
        {
            yield return 0;
            timer += Time.deltaTime;
            if (nodeList.Count != 0 && timer >= nodeList.First.Value.waitTime)
            {
                DoNode();
            }
        }
        yield return null;
    }

    //运行节点时间
    private void DoNode(LinkedListNode<TimerCon> curNode = null)
    {
        if (curNode == null)
        {
            curNode = nodeList.First;
        }
        if (curNode == null)
        {
            return;
        }
        if (timer >= curNode.Value.waitTime)
        {
            curNode.Value.action();
            if (curNode.Value.loopNum == -1 || curNode.Value.loopNum > 1)
            {
                curNode.Value.loopNum = curNode.Value.loopNum == -1 ? -1 : curNode.Value.loopNum - 1;
                StartTimeDown(curNode.Value._waitTime, curNode.Value.action, curNode.Value.loopNum);
            }
            nodeList.Remove(curNode);
            curNode = nodeList.First == null ? null : nodeList.First;

            if (curNode != null && timer >= curNode.Value.waitTime)
            {
                DoNode(curNode);
            }
        }

    }

}

 

所谓实际使用的封装

具体情况具体处理辣,肯定不能百分百的通用,是吧,嗯,我觉得是这样的

using System;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 实体类使用时构造一个TimeConEntity使用 
/// 非实体类 可直接使用TimerConManager
/// </summary>
public class TimeConEntity
{
    private List<Action> timerActions = new List<Action>();         //单个类里面管理计时事件  销毁的时候需要统一清理

    /// <summary>
    /// 开始计时
    /// </summary>
    /// <param name="waitTime">等待时间</param>
    /// <param name="action">事件</param>
    /// <param name="loopNum">循环次数 -1为无限循环</param>
    /// <returns></returns>
    public Action StartTimer(float waitTime, Action action, int loopNum = 0)
    {
     Action act = () => { }; act
= TimerConManager.Instance.StartTimeDown(waitTime, () => { if (this != null) { action(); } RemoveAction(act); }, loopNum);
     timerActions.Add(act);
return act; } /// <summary> /// 暂停计时 /// </summary> /// <param name="action">计时返回的事件</param> public void StopTimer(Action action) { TimerConManager.Instance.StopTimeDown(action); RemoveAction(action); } /// <summary> /// 清理自身管理数据 /// </summary> /// <param name="action">计时返回的事件</param> private void RemoveAction(Action action) { if (timerActions.Contains(action) == true) { timerActions.Remove(action); } } /// <summary> /// 清理全部计时 销毁时调用 /// </summary> public void Clear() { for (int i = 0; i < timerActions.Count; i++) { StopTimer(timerActions[i]); } timerActions.Clear(); } }

 

单例类继承模块 这个随意了~

public class UnitySlingleton<T> : MonoBehaviour where T : Component {
    private static T _instance = null;

    public static T Instance {
        get {
            if (_instance==null) {
                _instance = FindObjectOfType(typeof(T)) as T;
                if (_instance==null) {
                    GameObject obj = new GameObject();
                    obj.hideFlags = HideFlags.DontSave;
                    obj.name = typeof(T).Name;
                    obj.AddComponent<T>();
                }
            }
            return _instance;
        }
    }

    public virtual void Awake() {
        DontDestroyOnLoad(this.gameObject);
        if (_instance == null)
        {
            _instance = this as T;
        }
        else {
            GameObject.Destroy(this.gameObject);
        }
    }
}

 

posted @ 2023-06-13 18:08  狐狸爱看书  阅读(9)  评论(0编辑  收藏  举报