using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Cute; public class AsyncJob { private class Unit { public object action; public Action cancelAction; public Unit(object action, Action cancelAction) { this.action = action; this.cancelAction = cancelAction; } } private int num; private MonoBehaviour mono; private List jobList = new List(); private bool isCancel; private int? _waitFramesBetweenJobs; private int _waitFramesBetweenJobsMin; private FramerateProfiler _framerateProfiler = new FramerateProfiler(); public int WAIT_FRAMES_INCREMENT = 5; public int WAIT_FRAMES_DECREMENT = 1; public bool IsIdle { get { if (!isCancel) { return jobList.Count == 0; } return false; } } public int? WantedWaitFramesBetweenJobs { set { _waitFramesBetweenJobs = value; _waitFramesBetweenJobsMin = value.GetValueOrDefault(); } } public AsyncJob(MonoBehaviour mono, int num) { this.mono = mono; this.num = num; } public void Add(IEnumerator enumerator) { jobList.Add(new Unit(enumerator, null)); } public void Add(IEnumerator enumerator, Action calcelAction) { jobList.Add(new Unit(enumerator, calcelAction)); } public void Add(Action action) { jobList.Add(new Unit(action, null)); } public void Add(Action action, Action calcelAction) { jobList.Add(new Unit(action, calcelAction)); } public void Cancel() { if (!isCancel && jobList.Count != 0) { isCancel = true; Add(CancelTerminator, CancelTerminator); } } public void CancelTerminator() { isCancel = false; } public void Start() { for (int i = 0; i < num; i++) { mono.StartCoroutine(MicroThread()); } _framerateProfiler = new FramerateProfiler(); mono.StartCoroutine(RunFpsProfiler()); } private IEnumerator RunFpsProfiler() { _framerateProfiler.Init(); while (true) { _framerateProfiler.Update(); yield return null; } } private IEnumerator MicroThread() { while (true) { if (jobList.Count <= 0) { yield return null; continue; } Unit unit = jobList[0]; jobList.RemoveAt(0); if (isCancel) { if (unit.cancelAction != null) { unit.cancelAction(); } } else if (unit.action is IEnumerator) { yield return mono.StartCoroutine((IEnumerator)unit.action); if (!_waitFramesBetweenJobs.HasValue) { continue; } float? fps = _framerateProfiler.Fps; if (fps.HasValue) { if (fps < 20f) { _waitFramesBetweenJobs += WAIT_FRAMES_INCREMENT; _framerateProfiler.Init(); } else if (fps > 30f) { _waitFramesBetweenJobs -= WAIT_FRAMES_INCREMENT; if (_waitFramesBetweenJobs.Value < _waitFramesBetweenJobsMin) { _waitFramesBetweenJobs = _waitFramesBetweenJobsMin; } _framerateProfiler.Init(); } } yield return WaitFrames(_waitFramesBetweenJobs.Value); } else if (unit.action is Action) { ((Action)unit.action)(); } } } private static IEnumerator WaitFrames(int frameCount) { while (frameCount > 0) { frameCount--; yield return null; } } }