首页 > 其他分享 >Unity制作一个定时器Timer

Unity制作一个定时器Timer

时间:2024-05-21 15:08:38浏览次数:16  
标签:定时器 return void interval timer Unity Timer null public

Timer和TimerManager代码

using System.Collections;
using UnityEngine;
public class Timer : MonoBehaviour
{
    public delegate void Notifier();
    public Notifier onTimer;
    public Notifier onTimerReset;
    public Notifier onTimerComplete;
    public float interval;
    public int repeatCount = 0;

    public bool forever
    {
        get
        {
            return repeatCount == 0;
        }
    }
    public float time
    {
        get
        {
            if (running)
            {
                return crtCount * interval + Time.time - startTime;
            }
            return crtCount * interval + crtTime;
        }
    }
    protected float startTime;
    public int count
    {
        get
        {
            return crtCount;
        }
    }
    public bool complete
    {
        get
        {
            if (forever)
            {
                return false;
            }
            return crtCount == repeatCount;
        }
    }
    protected int crtCount = 0;
    protected float crtTime = 0f;
    public bool running = false;
    public void Dispose()
    {
        StopAllCoroutines();
        ClearNotifiers();
    }
    protected void OnDestroy()
    {
        ClearNotifiers();
    }
    public void Reset()
    {
        if (running)
        {
            ClearCoroutine();
        }
        crtCount = 0;
        crtTime = 0f;
        startTime = 0f;

        OnTimerReset();
    }
    public void ResetPlay()
    {
        Play(0f);
        OnTimerReset();
    }
    public void Stop()
    {
        if (running)
        {
            ClearCoroutine();
            crtTime = Time.time - startTime;
            if (crtTime >= interval)
            {
                crtTime = interval - 0.00001f;
            }
        }
    }
    public void Play()
    {
        if (!running)
        {
            Play(time);
        }
    }
    public void Play(float offset)
    {
        if (running)
        {
            ClearCoroutine();
        }

        if (offset < 0)
        {
            offset = 0;
        }
        else if (offset > 0 && !forever)
        {
            float totalTime = interval * repeatCount;
            if (offset > totalTime)
            {
                offset = totalTime;
            }
        }
        crtCount = Mathf.FloorToInt(offset / interval);
        crtTime = offset % interval;
        startTime = Time.time - crtTime;

        if (crtCount < repeatCount || forever)
        {
            StartCoroutine(Run());
            running = true;
        }
    }
    private IEnumerator Run()
    {
        while (true)
        {
            if (crtTime > 0)
            {
                yield return new WaitForSeconds(interval - crtTime);
                OnTimer();
                crtTime = 0;
            }
            yield return new WaitForSeconds(interval);
            OnTimer();
        }
    }
    private void OnTimer()
    {
        crtCount++;
        if (!forever && crtCount >= repeatCount)
        {
            ClearCoroutine();
        }
        else
        {
            startTime = Time.time;
        }

        if (onTimer != null)
        {
            onTimer();
        }
        if (onTimerComplete != null && !forever && crtCount >= repeatCount)
        {
            onTimerComplete();
        }
    }
    private void OnTimerReset()
    {
        if (onTimerReset != null)
        {
            onTimerReset();
        }
    }
    public void ClearNotifiers()
    {
        onTimer = null;
        onTimerComplete = null;
        onTimerReset = null;
    }
    private void ClearCoroutine()
    {
        StopAllCoroutines();
        running = false;
    }
}
using System.Collections.Generic;
using UnityEngine;

public class TimerManager : MonoBehaviour
{
    private const string MonoSingleName = "TimerManager";
    private static GameObject monoSingle;
    private static TimerManager instance;

    private bool destroyed { get; set; }

    public static bool HasInstance
    {
        get
        {
            return instance != null;
        }
    }

    public static TimerManager InitInstance()
    {
        return Instance;
    }


    public static TimerManager Instance
    {
        get
        {
            if (monoSingle == null)
            {
                monoSingle = GameObject.Find(MonoSingleName);
                if (monoSingle == null)
                {
                    monoSingle = new GameObject();
                    monoSingle.name = MonoSingleName;
                    //monoSingle.transform.SetParent(Core.Instance.transform);
                }
            }

            if (instance == null)
            {
                instance = monoSingle.GetComponent<TimerManager>();
                if (instance == null)
                {
                    instance = monoSingle.AddComponent<TimerManager>();
                }
                if (monoSingle.transform.parent == null)
                {
                    DontDestroyOnLoad(monoSingle);
                }
            }
            return instance;
        }
    }
    private GameObject timerGO;
    private List<Timer> freeTimers;

    protected void Awake()
    {
        timerGO = new GameObject();
        timerGO.name = "TimerCpts";
        timerGO.transform.SetParent(monoSingle.transform);

        freeTimers = new List<Timer>();
    }

    internal void Dispose()
    {
        if (timerGO != null)
        {
            Timer[] timers = timerGO.GetComponents<Timer>();
            for (int i = 0; i < timers.Length; i++)
            {
                timers[i].Dispose();
            }

            GameObject.Destroy(timerGO);
            timerGO = null;
        }
        freeTimers = null;
    }

    protected void OnDestroy()
    {
        if (!destroyed)
        {
            Dispose();
        }
    }

    /// <summary>
    /// 创建一个定时器
    /// </summary>
    /// <param name="interval">每N秒触发一次onTimer事件</param>
    /// <param name="repeatCount">一总触发多少次onTimer,所有出发完成后会自动删除,如果为0,forever</param>
    /// <returns></returns>
    private Timer CreateTimer(float interval, int repeatCount)
    {
        Timer timer = timerGO.AddComponent<Timer>();
        timer.interval = interval;
        timer.repeatCount = repeatCount;
        return timer;
    }

    /// <summary>
    /// 临时租用
    /// </summary>
    /// <param name="interval">间隔</param>
    /// <param name="repeatCount">最多触发次数如果为0,表示forever</param>
    /// <returns></returns>
    public Timer BorrowTimer(float interval, int repeatCount)
    {
        Timer timer;
        if (freeTimers.Count > 0)
        {
            timer = freeTimers[0];
            freeTimers.RemoveAt(0);
            timer.enabled = true;
            timer.interval = interval;
            timer.repeatCount = repeatCount;
        }
        else
        {
            timer = CreateTimer(interval, repeatCount);
        }
        return timer;
    }

    /// <summary>
    /// 归还,备下次用
    /// </summary>
    /// <param name="timer"></param>
    public void ReturnTimer(Timer timer)
    {
        if (destroyed)
            return;
        if (freeTimers.IndexOf(timer) != -1)
        {
            Debug.LogError("TimeMgr.ReturnTimer:freeTimers.IndexOf(timer) != -1,退还逻辑出错,请检查逻辑,同一个Timer被多次退还");
            return;
        }
        timer.Stop();
        timer.ClearNotifiers();
        timer.Reset();
        timer.enabled = false;
        freeTimers.Add(timer);
    }
}

测试用法:

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

public class Test : MonoBehaviour
{
    private Timer timer;
    void Start()
    {
        if (timer==null)
        {
            timer = TimerManager.Instance.BorrowTimer(3,5);
            timer.onTimer += Print;
            timer.Play();
        }
    }

    private void Print()
    {
        Debug.Log(Time.time);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

 

 

标签:定时器,return,void,interval,timer,Unity,Timer,null,public
From: https://www.cnblogs.com/weigangblog/p/18204079

相关文章

  • Unity制作一个BroadcastUI 跑马灯文字广播
     usingDG.Tweening;usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;usingUtils;//挂在UI上面publicclassBroadcastUI:MonoBehaviour{privateboolinited=false;privateBroadcastManbm;......
  • Unity查找物体和组件的方法
    一、找物体:①GameObject:a).Find(stringname)通过物体的名字查找b).FindWithTag(stringtag);通过标签获取添加该标签的一个物体c).FindObjectOfType();依据组件类型d).FindGameObjectsWithTag(stringtag)通过标签获取所有添加该标签的物体数组返回一个组合 ②Transform......
  • Unity的UnityEngine.EventSystems中的接口
    一、IPointerDownHandler,IPointerUpHandler,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandlerpublicvoidOnPointerClick(PointerEventDataeventData){Debug.Log("OnPointerClick,鼠标点击,在点击之后抬起时响应");}publicvoidOnP......
  • Unity编辑器Scene窗口快捷操作
    1.按住crtl,可以一个一个单位移动、缩放、旋转物体,单位距离在Edit-Snapsetting中设置,设置单位大小2.选中物体,按住alt+鼠标左键,可以环视目标物体3.按住V键,可以将物体的顶点接到其他物体的顶点 如果要设置更改其他在Scene窗口中的操作,可以利用MonoBehaviour下的OnDrawGizmos或......
  • Unity控制台console打印富文本
    可以用来控制Debug打印文本的 加粗斜体大小颜色Debug.Log("HelloWorld".AddBoldTag().AddColorTag("red"));publicstaticclassStringTagExt{publicstaticstringAddBoldTag(thisstringtext){returntext.AddTag("b");}......
  • Unity物体之间碰撞检测的方法
    检测碰撞有两种方式,一种是利用碰撞器,另外一种就是触发器。碰撞器的种类:1.StaticCollider静态碰撞器指的是相互碰撞的两个物体没有附加刚体而只附加了Collider的游戏对象。这类对象在碰撞时会保持静止,发生碰撞时不会触发任何的方法函数。 2.RigidbodyCollider刚体碰撞器......
  • Unity WebGL的一些配置
    添加自定义值方法:在网页模板中,添加<title>公司名字|{{{PROJECT_NAME}}}</title>///读取PlayerSettings.GetTemplateCustomValue("PROJECT_NAME");///设置PlayerSettings.SetTemplateCustomValue("PROJECT_NAME","这是一个自定义值");修改WebGL模板说......
  • flutter 定时器
    Timer?_timer;varperiodicTime="".obs;initTimer({requiredintcreateTime,requiredintduration})async{_timer=Timer.periodic(constDuration(seconds:1),(timer)async{DateTimecurrentTime=DateTime.now();varnow=(currentT......
  • Arch Linux CN Community repo mirrors list
    kate /etc/pacman.conf/etc/pacman.d/mirrorlist ##Ourmainserver(Amsterdam,theNetherlands)(ipv4,ipv6,http,https)[archlinuxcn]Server=https://repo.archlinuxcn.org/$arch ##CERNET(中国)(ipv4,ipv6,http,https)##Added:2023-08-19##Thiswill......
  • Unity优化总结(2021.04.08)
    项目性能优化的三个方面:1.CPU优化Cpu优化不够会出现的问题:由于短时间计算量太大,画面流畅性降低,出现跳帧发热严重,耗电量高(1)代码方面删除一些空的方法,尤其是Update等;使用for循环代替foreach,使用List代替ArrayList,尽量少使用封箱拆箱操作;循环中可以Break掉的直接退出循......