Unity在非继承自MonoBehaviour的脚本启动协程


在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;  
}

文章作者: 微笑紫瞳星
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 微笑紫瞳星 !
  目录