Unity编程笔记(三)定时任务管理器

using System.Collections.Generic;
using UnityEngine;

public delegate void TimeTaskDelegate();

/// 
/// 定时任务管理器
/// 
public class TimeManager :MonoBehaviour{
    /// 
    /// 定时任务列表
    /// 
    private List taskList = new List();

    private static TimeManager _timeInstance;
    public static TimeManager timeInstance
    {
        get
        {
            if (_timeInstance == null)
            {
                _timeInstance = FindObjectOfType(typeof(TimeManager)) as TimeManager;
                if(_timeInstance == null)
                {
                    GameObject obj = new GameObject("TimeManager");
                    obj.hideFlags = HideFlags.HideAndDontSave;
                    _timeInstance = (TimeManager)obj.AddComponent();  
                }
                return _timeInstance;
            }
            return _timeInstance;
        }
    }

    void Start()
    {
        DontDestroyOnLoad(this.gameObject);
        if (_timeInstance == null)
            _timeInstance = this as TimeManager;
    }
    
    /// 
    /// 添加定时任务
    /// 
    /// 延时执行时间间隔
    /// 是否可以重复执行
    /// 执行回调
    public void addTask(float timeDelay,bool repeat,TimeTaskDelegate timeTaskCallback)
    {
        addTask(new TimeTask(timeDelay, repeat, timeTaskCallback));
    }
    public void addTask(TimeTask taskToAdd)
    {
        if (taskList.Contains(taskToAdd)||taskToAdd == null) return;
        taskList.Add(taskToAdd);
    }

    /// 
    /// 移除定时任务
    /// 
    /// 
    /// 
    public bool removeTask(TimeTaskDelegate taskToRemove)
    {
        if (taskList.Count == 0 || taskToRemove == null) return false;
        foreach(TimeTask item in taskList)
        {
            if (item.timeTaskCallBack == taskToRemove)
                return taskList.Remove(item);
        }
        return false;
    }

    void Update()
    {
        Tick();
    }

    /// 
    /// 执行定时任务
    /// 
    private void Tick()
    {
        if (taskList == null) return;
        foreach (TimeTask task in taskList)
        {
            task.timeDelay -= Time.deltaTime;
            if (task.timeDelay <= 0)
            {
                task.timeTaskCallBack();
                task.timeDelay = task.timeDelayOnly;
            }
            if (!task.repeat)
                taskList.Remove(task);
        }
    }
}

/// 
/// 定时任务封装类
/// 
public class TimeTask
{
    /// 
    /// 延迟时间
    /// 
    private float _timeDelay;
    /// 
    /// 延迟时间
    /// 
    private float _timeDelayOnly;
    /// 
    /// 是否需要重复执行
    /// 
    private bool _repeat;
    /// 
    /// 回调函数
    /// 
    private TimeTaskDelegate _timeTaskCallBack;

    public float timeDelay { get { return _timeDelay; } set { _timeDelay = value; } }
    public float timeDelayOnly { get { return _timeDelayOnly; } }
    public bool repeat { get { return _repeat; } set { _repeat = value; } }
    public TimeTaskDelegate timeTaskCallBack { get { return _timeTaskCallBack; } }

    //构造函数
    public TimeTask(float timeDelay, bool repeat, TimeTaskDelegate timeTaskCallBack)
    {
        _timeDelay = timeDelay;
        _timeDelayOnly = timeDelay;
        _repeat = repeat;
        _timeTaskCallBack = timeTaskCallBack;
    }

    public TimeTask(float timeDelay, TimeTaskDelegate timeTaskCallBack) : this(timeDelay, true, timeTaskCallBack) { }
}
以上代码转载自: 参考链接: http://blog.csdn.net/henger_/article/details/73124046

注意,Tick()函数里面的foreach循环是有问题的,它会在移除item的时候破坏正在循环的数组,导致报错。

修改办法是,可以改成for循环,并在每次移除item的时候手动修改参数i

这个定时任务管理器将定时任务存进一个List中,然后每执行完一个任务,就弃掉,如果该任务需要重复执行,那就不弃掉,重置它的延迟时间然后继续执行。

每个任务的设计也很有意思,给任务一个延迟时间,然后每一帧去减少这个时间,当时间小于零的时候,就执行这个任务。

这种做减法的思路,还有将时间流分拆给每一个任务的思路很值得学习。

在自己的项目里重写了一个简易版的,并修复了循环内移除item引发的bug,还增加了计算最大时间的功能
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TimeTaskManager : MonoBehaviour {

    public static TimeTaskManager timeTaskManager;
    public float totalTime;

    private List taskList;

    private void Awake()
    {
        timeTaskManager = this;
        taskList = null;
    }
    public void AddTask(TimeTask _task)
    {
        if (taskList == null)
        {
            taskList = new List();
        }
        taskList.Add(_task);
    }
    public void ClearTaskList()
    {
        if (taskList != null)
        {
            taskList.Clear();
        }
    }
    public void CalculateTotalTime()
    {
        taskList.Sort();
        totalTime = (taskList[taskList.Count-1].time + taskList[taskList.Count-1].NoRepeatTime());
    }
    public void Tick()
    {
        if (taskList == null || taskList.Count == 0) { return; }     //如果空了就不再执行
        for (int i = 0; i < taskList.Count; i++)
        {
            TimeTask task = taskList[i];
            task.time -= Time.deltaTime;
            if (task.time <= 0)
            {
                task.TaskGo();
                if (task.isRepeat == true)
                {
                    task.time = task.repeatTime;
                }
                else
                {
                    taskList.Remove(task);
                    i--;
                }
            }
        }
    }
}
public class TimeTask:IComparable
{
    private int num;
    private float interval;
    private EnemyInfo enemyInfo;
    private BulletInfo bulletInfo;

    public float time;
    public bool isRepeat;
    public float repeatTime;

    public TimeTask(int _num,float _interval,EnemyInfo _enemyInfo,BulletInfo _bulletInfo,
                    float _time,bool _isRepeat,float _repeatTime)
    {
        num = _num;
        interval = _interval;
        enemyInfo = _enemyInfo;
        bulletInfo = _bulletInfo;
        time = _time;
        isRepeat = _isRepeat;
        repeatTime = _repeatTime;
    }
    public void TaskGo()
    {
        LaunchManager.launchManager.Launch_Ship(num,interval,enemyInfo,bulletInfo);
    }
    public float NoRepeatTime()
    {
        return num * interval;
    }

    public int CompareTo(TimeTask other)
    {
        float m_time = time + NoRepeatTime();
        float other_time = other.time + other.NoRepeatTime();
        if (m_time > other_time)
        {
            return 1;
        }
        else if (m_time == other_time)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }
}

你可能感兴趣的:(Unity编程)