在Unity中,协程通常是通过MonoBehaviour的StartCoroutine方法来启动的。很多时候,我们写逻辑层代码的时候也希望能够调用协程,例如网络通讯等功能,这就需要一个中介来帮你做这件事。这个中介通常是一个继承自MonoBehaviour的管理类,它可以提供启动和管理协程的方法。
以下是一个简单的协程管理类的实现:
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
/// <summary>
/// 协程启动类(适用于非继承自MonoBehaviour的脚本启动协程)
/// </summary>
public class CoroutineStarter : MonoBehaviour
{
private static CoroutineStarter _instance;
private static bool editor_mode = false;
private static CoroutineStarter Instance
{
get
{
#if UNITY_EDITOR
if (!Application.isPlaying) return null;
#endif
if (editor_mode) return null;
if (_instance == null)
{
GameObject obj = new GameObject("CoroutineStarter");
obj.AddComponent<CoroutineStarter>();
}
return _instance;
}
}
#if UNITY_EDITOR
private static void EditorApplicationStateChanged(PlayModeStateChange state)
{
switch (state)
{
case PlayModeStateChange.ExitingPlayMode:
editor_mode = true;
break;
case PlayModeStateChange.ExitingEditMode:
editor_mode = false;
break;
case PlayModeStateChange.EnteredEditMode:
editor_mode = true;
break;
case PlayModeStateChange.EnteredPlayMode:
editor_mode = false;
break;
}
}
#endif
void Awake()
{
_instance = this;
DontDestroyOnLoad(gameObject);
#if UNITY_EDITOR
EditorApplication.playModeStateChanged += EditorApplicationStateChanged;
#endif
}
/// <summary>
/// 启动协程(适用于在非继承自MonoBehaviour的脚本中启动协程),且通过该方法启动的协程不会因为切换场景而停止
/// </summary>
/// <param name="enumerator"></param>
public static Coroutine Start(IEnumerator enumerator)
{
if (Instance == null)
{
return null;
}
return Instance.StartCoroutine(enumerator);
}
/// <summary>
/// 停止由CoroutineStarter启动的协程
/// </summary>
/// <param name="coroutine"></param>
public static void Stop(Coroutine coroutine)
{
if (Instance == null) return;
Instance.StopCoroutine(coroutine);
}
private void OnDestroy()
{
_instance = null;
#if UNITY_EDITOR
EditorApplication.playModeStateChanged -= EditorApplicationStateChanged;
#endif
}
}
这个脚本使用时会自动生成一个空物体并完成挂载
使用时:
CoroutineStarter.Start(MyCoroutine());
IEnumerator MyCoroutine()
{
// 协程的逻辑代码
yield return null;
}