Unity 任务系统实现
任务系统包含一个管理类和事件类,通过重写事件类中的方法来实现事件生命周期内容(直接上代码)
接口类
public interface ITaskEvent
{
public enum ETaskStatus
{
NotStart = 0,
InProcessing,
Completed,
Failed
}
public enum ESyncType
{
Sync,
Async
}
public void Update();
public void Completed();
public void Failed();
public void Interrut();
public ESyncType GetSyncType();
public ETaskStatus GetStatus();
}
事件类
public abstract class TaskEvent : ITaskEvent
{
private ITaskEvent.ESyncType SyncType { get; set; }
private ITaskEvent.ETaskStatus Status { get; set; }
public event Action<TaskEvent, ITaskEvent.ETaskStatus> TaskStatusChange;
public virtual void Initialize(ITaskEvent.ESyncType syncType = ITaskEvent.ESyncType.Sync)
{
SyncType = syncType;
Status = ITaskEvent.ETaskStatus.NotStart;
}
public void Start()
{
Status = ITaskEvent.ETaskStatus.InProcessing;
TaskStatusChange?.Invoke(this, ITaskEvent.ETaskStatus.NotStart);
OnStart();
}
public void Update()
{
TaskStatusChange?.Invoke(this, ITaskEvent.ETaskStatus.InProcessing);
OnUpdate();
}
public void Completed()
{
if (GetStatus() == ITaskEvent.ETaskStatus.Failed) return;
Status = ITaskEvent.ETaskStatus.Completed;
TaskStatusChange?.Invoke(this, ITaskEvent.ETaskStatus.Completed);
OnCompleted();
}
public void Failed()
{
if (GetStatus() == ITaskEvent.ETaskStatus.Completed) return;
Status = ITaskEvent.ETaskStatus.Failed;
TaskStatusChange?.Invoke(this, ITaskEvent.ETaskStatus.Failed);
OnFailed();
}
public void Interrut()
{
Status = ITaskEvent.ETaskStatus.Completed;
TaskStatusChange?.Invoke(this, ITaskEvent.ETaskStatus.Completed);
OnInterrut();
}
protected virtual void OnUpdate() { }
protected virtual void OnStart() { }
protected virtual void OnCompleted() { }
protected virtual void OnFailed() { }
protected virtual void OnInterrut() { }
public ITaskEvent.ESyncType GetSyncType()
{
return SyncType;
}
public ITaskEvent.ETaskStatus GetStatus()
{
return Status;
}
}
管理类
(注:单例模式实现参考之前文章)
public class TaskEventManager : MonoSingleton<TaskEventManager>
{
private bool IsRunning { get; set; }
private bool Paused { get; set; }
private List<TaskEvent> TaskEvents { get; set; } = new();
private WaitForSeconds WaitHalfSeconds { get; set; } = new WaitForSeconds(0.5f);
private void Start()
{
IsRunning = true;
StartCoroutine(DoTask());
}
public TaskEvent AddTask(TaskEvent task)
{
task.Initialize();
TaskEvents.Add(task);
return task;
}
public void RemoveTask(TaskEvent task)
{
if (TaskEvents.Remove(task))
{
task.Interrut();
}
}
public void Pause()
{
Paused = true;
}
public void Resume()
{
Paused = false;
}
private IEnumerator DoTask()
{
yield return WaitHalfSeconds;
while (IsRunning)
{
if (Paused || TaskEvents.Count == 0)
{
yield return WaitHalfSeconds;
}
var indexer = 0;
while (indexer < TaskEvents.Count)
{
var task = TaskEvents[indexer];
switch (task.GetStatus())
{
case ITaskEvent.ETaskStatus.NotStart:
task.Start();
break;
case ITaskEvent.ETaskStatus.InProcessing:
task.Update();
break;
case ITaskEvent.ETaskStatus.Completed:
task.Completed();
break;
case ITaskEvent.ETaskStatus.Failed:
task.Failed();
break;
default:
throw new ArgumentOutOfRangeException();
}
if (task.GetSyncType() == ITaskEvent.ESyncType.Sync)
{
break;
}
indexer++;
}
for (var i = TaskEvents.Count - 1; i >= 0; i--)
{
var task = TaskEvents[i];
if (task.GetStatus() == ITaskEvent.ETaskStatus.Failed ||
task.GetStatus() == ITaskEvent.ETaskStatus.Completed)
{
RemoveTask(task);
}
}
yield return WaitHalfSeconds;
}
}
}