首页 > 其他分享 >计时器封装

计时器封装

时间:2023-06-13 18:25:16浏览次数:34  
标签:node 封装 waitTime 计时器 计时 action nodeList curNode

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

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

作为一个合格的程序员,我们不可能每次有计时都在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 = TimerConManager.Instance.StartTimeDown(waitTime, () =>
         {
             if (this != null)
             {
                 action();
             }
             RemoveAction(action);
         }, loopNum);
        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();
    }
}

 

标签:node,封装,waitTime,计时器,计时,action,nodeList,curNode
From: https://www.cnblogs.com/FoxLibrary/p/17428750.html

相关文章

  • Ease缓动函数封装
     什么是Ease缓动函数:Ease缓动函数是一种常见的动画效果函数,使用Ease缓动函数可以让动画效果看起来更加真实,时而加速时而减速,让动画不至于看上去太过“平凡”具体的缓动效果可以参考https://www.xuanfengge.com/easeing/easeing/算是比较简单的一个功能,就不墨迹了usingUn......
  • uni-app请求封装
    1.http.js//你的请求地址(线上或线下)exportconstBASE_URL='http://xxx.xxx.xx.xxx:xxxx/'; exportconsthttp=(options)=>{returnnewPromise((resolve,reject)=>{lettoken="",tokenName='';letheader={......
  • java ImageIO处理图像的封装
    评:packagecom.adam.dev.pic.easyImage;importjava.awt.AlphaComposite;importjava.awt.Color;importjava.awt.Font;importjava.awt.Graphics;importjava.awt.Graphics2D;importjava.awt.Point;importjava.awt.Rectangle;importjava.awt.co......
  • 83 封装 在类中设定私有属性 限定传入的参数的范围;当调用时,需要用set方法传参
    类 封装packagecom.fqs.demo061201;publicclassGirl{//属性Stringname;privateintage;//set赋值publicvoidsetAge(inta){if(age>18&&age<50){age=a;}else{System.out.println......
  • react echats封装
    import*asechartsfrom"echarts";import{EChartsOption}from'echarts'functionIndex(props:EChartsOption){constechartsRef:any=useRef<HTMLElement>();useEffect(()=>{constmyChart=echarts.init(echartsRef.cur......
  • 用C++封装的ADO类
    用C++封装的ADO类作者:刘振海.H文件//ADO.h:interfacefortheCADOclass.////#if!defined(AFX_ADO_H__5A466E67_5E04_445D_9CB0_C64650B9AC68__INCLUDED_)#defineAFX_ADO_H__5A466E67_5E04_445D_9CB0_C64650B9AC68__INCLUDED_#if_MSC_VER>1000#pragmaonce......
  • React - 06 初步尝试封装组件
    1.封装dialog组件调用2.函数组件是静态组件/*函数组件是“静态组件”第一次渲染组件,把函数执行+产生一个私有的上下文:EC(V)+把解析出来的props「含children」传递进来「但是被冻结了」+对函数返回的JSX元素「virtualDOM」进行渲染当我们点击按钮的......
  • 聊聊结合业务需求给出合理的技术解决方案,改进现有模块功能,提高系统的可扩展性,封装性,稳
    针对提高系统的可扩展性、封装性、稳定性,改进现有模块功能,以下是我给出的一些技术解决方案:使用面向对象编程的设计模式:可以采用一些设计模式如单例模式、工厂模式、观察者模式等,来提高系统的可扩展性和封装性。应用微服务架构:可以将系统拆分成多个独立的服务,使得每个服务都可......
  • el-dialog-form组件封装,真的好用,可以让你开发效率提高
    1、新建DialogForm.vue文件<template><divclass="base-dialog"><el-dialog:type="type":custom-class="customClass":close-on-click-modal="closeOnClickModal":visible="vi......
  • vue+elementUI 搜索栏公共组件封装,封装多搜索条件通用组件,超实用
    1、新建BaseSearch.vue文件<!--*名称:弹窗的搜索条件组件*功能:methods1.点击搜索的方法:@search2.搜索条件props:formItemList--><template><divclass="dialog-search"><el-form:inline="true"ref="......