yukamu 发表于 2021-7-15 17:57

Unity怎么暂停协程Unity协程管理方案

协程是游戏开发中非常常用的方法,类似一个子线程单独出来处理一些问题,性能开销较小。当然我们更多时候用的是他的延时执行功能

使用多了,难免有这样那样的需求。比如:暂停。比如:管理大量协程等
协程要在Mono类执行,销毁物体会停止协程,咋办

下面提供协程的一个管理器方案。

核心类有3个:


image.png

使用的时候只需要使用CoroutineMgr
CoroutineItem

using System.Collections;using UnityEngine;public class CoroutineItem : MonoBehaviour{    public enum CoroutineState{      WAITTING,      RUNNING,      PASUED,      STOP    }    public CoroutineState State{get;set;}    public IEnumerator Body(IEnumerator routine){      while(State == CoroutineState.WAITTING){            yield return null;      }      while(State == CoroutineState.RUNNING){            if(State == CoroutineState.PASUED){                yield return null;            }else{                if(routine!=null&&routine.MoveNext()){                  yield return routine.Current;                }else{                  State = CoroutineState.STOP;                }            }      }    }}CoroutineCtrl

using System.Collections;using UnityEngine;public class CoroutineCtrl{    private static int _id;    public int ID{get;private set;}    private CoroutineItem _item;    private MonoBehaviour _mono;    private IEnumerator _routine;    private Coroutine _coroutine;    public CoroutineCtrl(MonoBehaviour mono, IEnumerator routine)    {      _item = new GameObject().AddComponent<CoroutineItem>();      _mono = mono;      _routine = routine;      ResetData();    }    public void Start()    {      _item.State = CoroutineItem.CoroutineState.RUNNING;      _coroutine = _mono.StartCoroutine(_item.Body(_routine));    }    public void Pause()    {      _item.State = CoroutineItem.CoroutineState.PASUED;    }    public void Stop()    {      _item.State = CoroutineItem.CoroutineState.STOP;    }    public void Continue()    {      _item.State = CoroutineItem.CoroutineState.RUNNING;    }    public void ResetStart()    {      if(_coroutine != null){            _mono.StopCoroutine(_coroutine);      }      Start();    }    private void ResetData(){      ID = _id++;    }}CoroutineMgr

using System.Collections;using System.Collections.Generic;using UnityEngine;public class CoroutineMgr : MonoSingleton<CoroutineMgr>{    private Dictionary<int,CoroutineCtrl> _ctrlDic;    public CoroutineMgr(){      _ctrlDic = new Dictionary<int, CoroutineCtrl>();    }    public int Execute(IEnumerator routine,bool autoStart = true){      CoroutineCtrl ctrl = new CoroutineCtrl(this,routine);      _ctrlDic.Add(ctrl.ID,ctrl);      if(autoStart){            StartExecute(ctrl.ID);      }                return ctrl.ID;    }    public void ExecuteOnce(IEnumerator routine){      CoroutineCtrl ctrl = new CoroutineCtrl(this,routine);      ctrl.Start();    }    public void StartExecute(int id){      var ctrl = GetCtrl(id);      if(ctrl!=null){            ctrl.Start();      }    }    public void PauseExecute(int id){      var ctrl = GetCtrl(id);      if(ctrl!=null){            ctrl.Pause();      }    }    public void StopExecute(int id){      var ctrl = GetCtrl(id);      if(ctrl!=null){            ctrl.Stop();      }    }   public void RestartExecute(int id){      var ctrl = GetCtrl(id);      if(ctrl!=null){            ctrl.ResetStart();      }    }   private CoroutineCtrl GetCtrl(int id){      if(_ctrlDic.ContainsKey(id)){            return _ctrlDic;      }else{            Debug.LogError($"当前id不存在,id:{id}");            return null;      }    }}MonoSingleton

//简易的Mono单例类,如无必要,代码中尽量少用using UnityEngine;public class MonoSingleton<T> : MonoBehaviour where T:MonoBehaviour{    private static T _instance;    public static T Instance {      get {            if(_instance == null)            {                GameObject go = new GameObject(typeof(T).Name);                DontDestroyOnLoad(go);                _instance = go.AddComponent<T>();            }            return _instance;      }    }}测试

using System.Collections;using UnityEngine;using UnityEngine.UI;public class CoroutineTest : MonoBehaviour{    public Button mBtnStart;    public Button mBtnPause;    public Button mBtnStop;    private int id = 0;    private void Awake()    {      mBtnStart.onClick.AddListener(ClickStart);      mBtnPause.onClick.AddListener(ClickPause);      mBtnStop.onClick.AddListener(ClickStop);    }    private void Start()    {      // CoroutineMgr.Instance.ExecueOnce(DoSomething()); 只需要执行一次,不需要控制的用这个      id = CoroutineMgr.Instance.Execute(DoSomething());//需要多次执行和管理的用这个,保存下id,用id调用控制方法    }    void ClickStart()    {         CoroutineMgr.Instance.RestartExecute(id);    }    void ClickPause()    {      CoroutineMgr.Instance.PauseExecute(id);    }    void ClickStop()    {      CoroutineMgr.Instance.StopExecute(id);    }    IEnumerator DoSomething()    {      print($"当前携程ID为{id}");      print("协程开始");      var timer = 0;      while ( timer<30)      {            yield return new WaitForSeconds(1);            timer++;            print($"协程进行第{timer}秒");      }      print("协程完成");    }}
以上方案出自Siki学院Andy老师《全民飞机大战》框架设计系列
页: [1]
查看完整版本: Unity怎么暂停协程Unity协程管理方案