繁体   English   中英

在 Unity 中使用 C# 从 static 方法调用 IEnumerator 的最佳方式

[英]Best way to call an IEnumerator from a static method in Unity with C#

编辑:Unity - C#

你能给我一些信息和提示我如何从 static 方法启动 IEnumerator。 到目前为止,我所知道的是以下选项:

A):使调用IEnumerator的方法(METHOD_1)为非static,然后像这样搜索脚本

FindObjectOfType<Scriptname>().METHOD_1();

B):使用 MonoBehaviour 启动协程

Scriptname.METHOD_1(this);

public static void METHOD_1(MonoBehaviour StartThisStatic)
{
    StartThisStatic.StartCoroutine(Test());
}
public static IEnumerator Test()
{
    yield return new WaitForSeconds(2f);
}

C):在唤醒/启动中使用实例

就性能和稳定性而言,最佳选择是什么? 可以简单的给我解释一点背景知识吗?

非常感谢!

我从无法做到这一点的地方启动协程的解决方案是制作 Singleton CoroutineManager。 然后我使用这个 CoroutineManager 从 ScriptableObjects 之类的地方调用这些 Coroutine。 您还可以使用它来缓存 WaitForEndOfFrame 或 WaitForFixedUpdate,这样您就不需要每次都创建新的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoroutineController : MonoBehaviour
{

    static CoroutineController _singleton;
    static Dictionary<string,IEnumerator> _routines = new Dictionary<string,IEnumerator>(100);

    [RuntimeInitializeOnLoadMethod( RuntimeInitializeLoadType.BeforeSceneLoad )]
    static void InitializeType ()
    {
        _singleton = new GameObject($"#{nameof(CoroutineController)}").AddComponent<CoroutineController>();
        DontDestroyOnLoad( _singleton );
    }

    public static Coroutine Start ( IEnumerator routine ) => _singleton.StartCoroutine( routine );
    public static Coroutine Start ( IEnumerator routine , string id )
    {
        var coroutine = _singleton.StartCoroutine( routine );
        if( !_routines.ContainsKey(id) ) _routines.Add( id , routine );
        else
        {
            _singleton.StopCoroutine( _routines[id] );
            _routines[id] = routine;
        }
        return coroutine;
    }
    public static void Stop ( IEnumerator routine ) => _singleton.StopCoroutine( routine );
    public static void Stop ( string id )
    {
        if( _routines.TryGetValue(id,out var routine) )
        {
            _singleton.StopCoroutine( routine );
            _routines.Remove( id );
        }
        else Debug.LogWarning($"coroutine '{id}' not found");
    }
    public static void StopAll () => _singleton.StopAllCoroutines();
    
}

然后:

CoroutineController.Start( Test() );

您还可以通过给它们标签来停止特定的协程:

CoroutineController.Start( Test() , "just a test" );

// <few moments later, meme>

CoroutineController.Stop( "just a test" );

为了更好地理解这个概念,请查看 CoroutineController class 的绝对最低版本。 它只是一个字段和一个方法,仅此而已:

using UnityEngine;
public class CoroutinePawn : MonoBehaviour
{
    public static CoroutinePawn Instance { get; private set; }

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void InitializeType ()
    {
        Instance = new GameObject($"#{nameof(CoroutinePawn)}").AddComponent<CoroutinePawn>();
        DontDestroyOnLoad( Instance );
    }
}

因为这个Instance static 字段为您提供了对现有MonoBehaviour (GameObject) 的引用 - 您可以从任何地方手动启动协程:

CoroutinePawn.Instance.StartCoroutine( Test() );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM