美文网首页
Clock计时器

Clock计时器

作者: 乐子下午要上课 | 来源:发表于2019-05-09 15:33 被阅读0次
     public class Clock
    {
        private List<System.Action> updateObservers = new List<System.Action>();
        private Dictionary<System.Action, Timer> timers = new Dictionary<System.Action, Timer>();
        private HashSet<System.Action> removeObservers = new HashSet<System.Action>();
        private HashSet<System.Action> addObservers = new HashSet<System.Action>();
        private HashSet<System.Action> removeTimers = new HashSet<System.Action>();
        private Dictionary<System.Action, Timer> addTimers = new Dictionary<System.Action, Timer>();
        private bool isInUpdate = false;
    
        class Timer
        {
            public double absoluteTime = 0f;
            public int repeat = 0;
            public bool used = false;
        }
    
        private double elapsedTime = 0f;
    
        private List<Timer> timerPool = new List<Timer>();
        private int currentTimerPoolIndex = 0;
    
        /// <summary>Register a timer function</summary>
        /// <param name="time">time in milliseconds</param>
        /// <param name="repeat">number of times to repeat, set to -1 to repeat until unregistered.</param>
        /// <param name="action">method to invoke</param>
        public void AddTimer(float time, int repeat, System.Action action)
        {
            AddTimer(time, 0f, repeat, action);
        }
    
        /// <summary>Register a timer function with random variance</summary>
        /// <param name="time">time in milliseconds</param>
        /// <param name="randomVariance">deviate from time on a random basis</param>
        /// <param name="repeat">number of times to repeat, set to -1 to repeat until unregistered.</param>
        /// <param name="action">method to invoke</param>
        public void AddTimer(float time, float randomVariance, int repeat, System.Action action)
        {
            time = time - randomVariance * 0.5f + randomVariance * UnityEngine.Random.value;
            if (!isInUpdate)
            {
                if (this.timers.ContainsKey(action))
                {
                    Assert.IsTrue(this.timers[action].used);
                    this.timers[action].absoluteTime = elapsedTime + time;
                    this.timers[action].repeat = repeat;
                }
                else
                {
                    this.timers[action] = getTimerFromPool(elapsedTime + time, repeat);
                }
            }
            else
            {
                if (!this.addTimers.ContainsKey(action))
                {
                    this.addTimers[action] = getTimerFromPool(elapsedTime + time, repeat);
                }
                else
                {
                    Assert.IsTrue(this.addTimers[action].used);
                    this.addTimers[action].repeat = repeat;
                    this.addTimers[action].absoluteTime = elapsedTime + time;
                }
    
                if (this.removeTimers.Contains(action))
                {
                    this.removeTimers.Remove(action);
                }
            }
        }
    
        public void RemoveTimer(System.Action action)
        {
            if (!isInUpdate)
            {
                if (this.timers.ContainsKey(action))
                {
                    timers[action].used = false;
                    this.timers.Remove(action);
                }
            }
            else
            {
                if (this.timers.ContainsKey(action))
                {
                    this.removeTimers.Add(action);
                }
                if (this.addTimers.ContainsKey(action))
                {
                    Assert.IsTrue(this.addTimers[action].used);
                    this.addTimers[action].used = false;
                    this.addTimers.Remove(action);
                }
            }
        }
    
        public bool HasTimer(System.Action action)
        {
            if (!isInUpdate)
            {
                return this.timers.ContainsKey(action);
            }
            else
            {
                if (this.removeTimers.Contains(action))
                {
                    return false;
                }
                else if (this.addTimers.ContainsKey(action))
                {
                    return true;
                }
                else
                {
                    return this.timers.ContainsKey(action);
                }
            }
        }
    
        /// <summary>Register a function that is called every frame</summary>
        /// <param name="action">function to invoke</param>
        public void AddUpdateObserver(System.Action action)
        {
            if (!isInUpdate)
            {
                this.updateObservers.Add(action);
            }
            else
            {
                if (!this.updateObservers.Contains(action))
                {
                    this.addObservers.Add(action);
                }
                if (this.removeObservers.Contains(action))
                {
                    this.removeObservers.Remove(action);
                }
            }
        }
    
        public void RemoveUpdateObserver(System.Action action)
        {
            if (!isInUpdate)
            {
                this.updateObservers.Remove(action);
            }
            else
            {
                if (this.updateObservers.Contains(action))
                {
                    this.removeObservers.Add(action);
                }
                if (this.addObservers.Contains(action))
                {
                    this.addObservers.Remove(action);
                }
            }
        }
    
        public bool HasUpdateObserver(System.Action action)
        {
            if (!isInUpdate)
            {
                return this.updateObservers.Contains(action);
            }
            else
            {
                if (this.removeObservers.Contains(action))
                {
                    return false;
                }
                else if (this.addObservers.Contains(action))
                {
                    return true;
                }
                else
                {
                    return this.updateObservers.Contains(action);
                }
            }
        }
    
        public void Update(float deltaTime)
        {
            this.elapsedTime += deltaTime;
    
            this.isInUpdate = true;
    
            foreach (System.Action action in updateObservers)
            {
                if (!removeObservers.Contains(action))
                {
                    action.Invoke();
                }
            }
    
            Dictionary<System.Action, Timer>.KeyCollection keys = timers.Keys;
            foreach (System.Action timer in keys)
            {
                if (this.removeTimers.Contains(timer))
                {
                    continue;
                }
    
                Timer time = timers[timer];
                if (time.absoluteTime <= this.elapsedTime)
                {
                    if (time.repeat == 0)
                    {
                        RemoveTimer(timer);
                    }
                    else if (time.repeat >= 0)
                    {
                        time.repeat--;
                    }
                    timer.Invoke();
                }
            }
    
            foreach (System.Action action in this.addObservers)
            {
                this.updateObservers.Add(action);
            }
            foreach (System.Action action in this.removeObservers)
            {
                this.updateObservers.Remove(action);
            }
            foreach (System.Action action in this.addTimers.Keys)
            {
                if (this.timers.ContainsKey(action))
                {
                    Assert.AreNotEqual(this.timers[action], this.addTimers[action]);
                    this.timers[action].used = false;
                }
                Assert.IsTrue(this.addTimers[action].used);
                this.timers[action] = this.addTimers[action];
            }
            foreach (System.Action action in this.removeTimers)
            {
                Assert.IsTrue(this.timers[action].used);
                timers[action].used = false;
                this.timers.Remove(action);
            }
            this.addObservers.Clear();
            this.removeObservers.Clear();
            this.addTimers.Clear();
            this.removeTimers.Clear();
    
            this.isInUpdate = false;
        }
    
        public int NumUpdateObservers
        {
            get
            {
                return updateObservers.Count;
            }
        }
    
        public int NumTimers
        {
            get
            {
                return timers.Count;
            }
        }
    
        public double ElapsedTime
        {
            get
            {
                return elapsedTime;
            }
        }
    
        private Timer getTimerFromPool(double absoluteTime, int repeat)
        {
            int i = 0;
            int l = timerPool.Count;
            Timer timer = null;
            while (i < l)
            {
                int timerIndex = (i + currentTimerPoolIndex) % l;
                if (!timerPool[timerIndex].used)
                {
                    currentTimerPoolIndex = timerIndex;
                    timer = timerPool[timerIndex];
                    break;
                }
                i++;
            }
    
            if (timer == null)
            {
                timer = new Timer();
                currentTimerPoolIndex = 0;
                timerPool.Add(timer);
            }
    
            timer.used = true;
            timer.absoluteTime = absoluteTime;
            timer.repeat = repeat;
            return timer;
        }
        
        public int DebugPoolSize
        {
            get
            {
                return this.timerPool.Count;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Clock计时器

          本文链接:https://www.haomeiwen.com/subject/bvwwoqtx.html