Unity3d 设计自己的单个计时类

程序和游戏中往往有很多需要计时的地方,比如很多日常任务是领取后倒计时到了就可以完成的。于是之前做游戏的时候设计了一个计时类Timer,需要使用的时候实例化一个Timer,并且在Update中进行计时即可。
首先确定实现计时器需要哪些变量和功能。我们需要判断计时器是否在工作,总的计时时长,当前的计时时长和计时的进程。我们还需要一些简单的方法,如开始,暂停,恢复,停止等,当然在各个方法执行的时候能够针对不同的情况相应一些事件也是必须的,不然这个计时器就不具备了通用性。知道了这些我们就可以开始设计我们的计时器了,其中计时器已秒为单位,我们可以进行更改定义自己需要的单位。
首先定义一些变量,这里使用了Get和Set来设置属性。

using UnityEngine;

[System.Serializable]
public class SingleTimer
{

    public bool _running;
    private float _curTime;
    private float _targetTime;
    private float _process;

    public float time
    {
        get { return _curTime; }
    }

    public float tartetTime
    {
        get { return _targetTime; }
    }

    public float process
    {
        get
        {
            return _process;
        }
        set
        {
            _process = Mathf.Clamp01(value);
            _curTime = _targetTime * _process;
        }
    }

    public bool IsRunning()
    {
        return _running;
    }

    public delegate void EventHandler();
    public event EventHandler startEvent;
    public event EventHandler tickEvent;
    public event EventHandler endEvnet;
    public event EventHandler pauseEvent;
    public event EventHandler stopEvent;
    public event EventHandler resetEvent;

    public SingleTimer()
    {
        _curTime = 0;
        _process = 0;
        _running = false;
    }

    public SingleTimer(float target, bool autoStart)
    {
        if (target < 0)
        {
#if UNITY_EDITOR
            Debug.Log("Target time must larger than 0");
#endif
            target = 0;
        }
        _targetTime = target;
        _curTime = 0;
        _process = 0;
        _running = autoStart;
    }

    public SingleTimer(float target, float p, bool autoStart)
    {
        if (target < 0)
        {
#if UNITY_EDITOR
            Debug.Log("Target time must larger than 0");
#endif
            target = 0;
        }
        _targetTime = target;
        _process = Mathf.Clamp01(p);
        _curTime = _targetTime * _process;
        _running = autoStart;
    }

    public void SetTargetTime(float target)
    {
        if (target < 0)
        {
#if UNITY_EDITOR
            Debug.Log("Target time must larger than 0");
#endif
            target = 0;
        }
        _targetTime = target;
    }

    public void TimerStart()
    {
        _running = true;
        if (startEvent != null)
            startEvent();
    }

    public void TimerPause()
    {
        _running = false;
        if (pauseEvent != null)
            pauseEvent();
    }

    public void TimerStop()
    {
        _process = 0;
        _curTime = 0;
        _running = false;
        if (stopEvent != null)
            stopEvent();
    }

    public void TimerReset()
    {
        _process = 0;
        _curTime = 0;
        _running = false;
        if (resetEvent != null)
            resetEvent();
    }

    public void TimerTick(float deltaTime)
    {
        if (_running)
        {
            _curTime += deltaTime;
            _process = _curTime / _targetTime;
            if (tickEvent != null)
                tickEvent();

            if (_process >= 1)
            {
                _process = 1;
                _curTime = _targetTime;
                _running = false;
                if (endEvnet != null)
                    endEvnet();
            }
        }
    }

    public void ReStartTimer()
    {
        _process = 0;
        _curTime = 0;
        _running = true;
        if (startEvent != null)
            startEvent();
    }

    public void ReStartTimer(float changeTarget)
    {
        if (changeTarget < 0)
        {
#if UNITY_EDITOR
            Debug.Log("Target time must larger than 0");
#endif
            changeTarget = 0;
        }
        _targetTime = changeTarget;
        _process = 0;
        _curTime = 0;
        _running = true;
        if (startEvent != null)
            startEvent();
    }

}

调用:

 public SingleTimer time;
        void Start()
        {
            time = new SingleTimer(5, true);
            time.endEvnet += Time_endEvnet;
        }

        private void Time_endEvnet()
        {
            time = null;
            Debug.Log("end");
        }

        private void Update()
        {
            if (time != null)
            {
                time.TimerTick(Time.deltaTime);
                if (time != null)
                {
                    Debug.Log(time.time);
                }

            }
        }
private bool _running;
private float _curTime;
private float _targetTime;
private float _process;

public float tartetTime
{
    get { return _targetTime; }
}

public float process
{
    get
    {
        return _process;
    }
    set
    {
        _process = Mathf.Clamp01(value);
        _curTime = _targetTime * _process;
    }
}

public bool IsRunning()
{
    return _running;
}

然后我们用委托机制来实现我们需要自定义的事件。

public delegate void EventHandler();

// 计时器开始事件
public event EventHandler startEvent;
// 计时器计时事件
public event EventHandler tickEvent;
// 计时器结束事件
public event EventHandler endEvnet;
// 计时器暂停事件
public event EventHandler pauseEvent;
// 计时器停止事件
public event EventHandler stopEvent;
// 计时器重置事件
public event EventHandler resetEvent;

当我们实例化一个Timer对象之后,只需添加对应的事件即可,当然是用+=时不要忘记在合适的事件对应地-=。

Timer timer = new Timer();

void OnEnable()
{
    timer.endEvent += OnTimerEnd;
}

void OnDisable()
{
    timer.endEvent -= OnTimerEnd;
}

void OnTimerEnd() 
{
    Debug.Log("Timer End");
}

当然我们实例化计时类的时候需要一个目标值,并且设置是否自动启动计时器。当然我们也可以定义一些自己需要的内容,比如在特定的时间点处启动等。代码如下:

public Timer(float target, bool autoStart)
{
    if (target < 0)
    {
#if UNITY_EDITOR
        Debug.Log("Target time must larger than 0");
#endif
        target = 0;
    }

    _targetTime = target;
    _curTime = 0;
    _process = 0;
    _running = autoStart;
}

最后就是控制计时器的一个方法,比如开始,暂停之类的,在每个方法中调用定义的委托事件。在调用之前需要先判断一下是否有委托,不然会报错。

public void TimerStart()
{
    _running = true;
    if (startEvent != null)
        startEvent();
}

public void TimerPause()
{
    _running = false;
    if (pauseEvent != null)
        pauseEvent();
}

public void TimerStop()
{
    _process = 0;
    _curTime = 0;
    _running = false;
    if (stopEvent != null)
        stopEvent();
}

public void TimerReset()
{
    _process = 0;
    _curTime = 0;
    _running = false;
    if (resetEvent != null)
        resetEvent();
}

public void ReStartTimer()
{
    _process = 0;
    _curTime = 0;
    _running = true;
    if (startEvent != null)
        startEvent();
}

最后也是最重要的一个函数,就是实现计时器计时功能的方法,这个方法需要在脚本的Update中进行调用,或者在协程等一些可以计时的地方进行调用。我们给这个函数传入一个float类型的时间间隔,让计时器不断更新当前时间,当进行到达1的时候计时就结束了。

public void TimerTick(float deltaTime)
{
    if (_running)
    {
        _curTime += deltaTime;
        _process = _curTime / _targetTime;
        if (tickEvent != null)
            tickEvent();

        if (_process >= 1)
        {
            _process = 1;
            _curTime = _targetTime;
            _running = false;
            if (endEvnet != null)
                endEvnet();
        }
    }
}

在我们需要使用计时器的脚本中,建议先判断计时器是否为null来避免我们删除计时器后的报错情况:

Timer timer = new Timer(60, true);

void Update()
{
    if(timer != null)
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值