[英]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.