unity 计时器

Posted CZandQZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity 计时器相关的知识,希望对你有一定的参考价值。

    计时器的作用嘛就是简单的计时了,说白了就是一段时间一直减就行了,简单的代码如下。我们可以放在Update里面计时,同时我们也可以通过携程来计时,2中代码如下:

      private void Update()
        

            totalTime -= Time.deltaTime;
            if (totalTime <= 0)
            
                //todo:计时结束
            

        
这是放在Update里面的那种还有·另外一种:

     private float totalTime1 = 4;
        private IEnumerator Do()
        
            while (true)
            
                totalTime1 -= Time.deltaTime;
                if (totalTime1 <= 0)
                
                    //todo:计时结束
                    yield break;
                

                yield return null;
            
        
后面一种通过携程来实现的 同样都比较简单,如果我们需要对一个拾取的加速道具计时的话,我们需要写一个speedTotalTime。如果再拾取一个无敌道具我们岂不是又要在这个类中添加另外一个变量么,要是这样写下去这个类就会变得很乱了么,所以写计时器的目的是为了能够让他变成一个工具,耦合性变得最低,这样所有需要用到计时器的项目都可以用到它,这里我们建一个基本的Timer类

 public class Timer
    

        public float Duration;

        public float LeftTime;


        private Action _updateAction;

        private Action _callAction;

        private bool _isPause;

        public Timer(float duration,Action updateAction=null,Action callAction=null,Action intiAction = null)
        
            LeftTime = duration;

            Duration = duration;

            if (intiAction != null) intiAction.Invoke();

            _updateAction = updateAction;

            _callAction = callAction;

            _isPause = false;

        


        public void OnUpdate(float deltaTime)
        

            LeftTime -= deltaTime;
            if (LeftTime <= 0)
            
                if (_callAction != null)
                    _callAction.Invoke();
            
            else
            
                if (_updateAction != null && !_isPause)
                    _updateAction.Invoke();  
            
        


        public void SetTimerTrick(bool b)
        
            _isPause = b;
        
    
Timer类基本必须的2个变量一个是这个计时器总共持续时间,还有就是这个计时器走了多长时间(即我们得知道还剩余多少时间),这些都是一个计时器都是最基本的,还有就是对计时器初始化时我们所需做的事件,计时器计时的我们所需做的操作,计时器计时结束的回调。同样我们需要对每个计时器进行管理,所以我们需要一个管理器。我们起名为TimerManager,既然是管理器那么他就存在2个基本的方法,AddTimer和RemoveTimer。所以具体代码如下:
public class TimerManager : Singleton<TimerManager>
    
        private List<Timer> _timers;
        private Dictionary<string, Timer> _timerDict;
 

        private void Awake()
        
            _timers = new List<Timer>();
            _timerDict = new Dictionary<string, Timer>();
        


        private void Update()
        

            for (int i = 0; i < _timers.Count; i++)
            
                _timers[i].OnUpdate(Time.deltaTime);
            

        

        public void AddTimer(string str,Timer timer)
        
            if (_timerDict.ContainsKey(str))
            
                _timerDict[str].LeftTime += _timerDict[str].Duration;
            
            else
            
                _timerDict.Add(str, timer);
                _timers.Add(timer);
            

        

        public void RemoveTimer(string str)
        
            var timer = _timerDict[str];
            if (timer != null)
            
                _timers.Remove(timer);
                _timerDict.Remove(str);
            
        
    
AddTimer主要的作用是往管理器中添加一个计时器,如果我们拾取一个加速道具的时候,在加速还没有结束的时候我们又拾取一个加速道具这时我们需要把道具的持续时间延长这时就需要对计时器的LeftTime变长。所以 _timerDict[str].LeftTime += _timerDict[str].Duration;如果机器是管理器。最后就是一个Update方法来统一管理计时器的计时了。

接下来就是运用一下计时器了。这里我们用道具来测试一下代码。当我们在拾取道具的时候我们需要判断是拾取加速道具还是无敌道具等其他的一些道具,这时候的判断就就得用if else来判断这样做的。当我们新添加一种道具的时候我们岂不是又要修改原先的代码了,所以我们得用面向对象的思想来解决这个问题。我们建一个基类:

  public abstract class BaseProp:MonoBehaviour
    

        public float Duration;

        public abstract void Excute(Transform t);

    
然后我们的加速道具就应该继承这个基类了
  public class SpeedProp : BaseProp
    
        public override void Excute(UnityEngine.Transform t)
        
            var entity = t.GetComponent<TestPlayerEntity>();
            TimerManager.Instance.AddTimer("Speed",new Timer(Duration,null, () =>
            
                DecreaseSpeed(entity);
                TimerManager.Instance.RemoveTimer("Speed");

            , () =>
            
                IncreaseSpeed(entity);
            ));

        

        private void IncreaseSpeed(TestPlayerEntity entity)
        
            if (entity != null)
            
                entity.MoveSpeed = 3;
            
        


        private void DecreaseSpeed(TestPlayerEntity entity)
        
            if (entity != null)
            
                entity.MoveSpeed = 1;
            
        

        
    
接着我们的玩家类在碰到道具的时候只需
      public void OnTriggerEnter2D(Collider2D collision)
        

            if (collision.transform.CompareTag("Prop"))
            
                collision.GetComponent<BaseProp>().Excute(this.transform);
            

        
这样就避免了一长串的判断语句了同时解决了代码的耦合性了。好了这节就讲到这里了。






以上是关于unity 计时器的主要内容,如果未能解决你的问题,请参考以下文章

Unity 背包道具搜索

关于Unity中的道具拾取(专题六)

unity玩家血量控制,定时掉血,道具加血

Ruby‘s Adventrue游戏制作笔记Unity采集生命道具

Ruby‘s Adventrue游戏制作笔记Unity采集生命道具

jQuery计时器写剩余时间