UnityScript,在FSM中使用协同程序的静态方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UnityScript,在FSM中使用协同程序的静态方法相关的知识,希望对你有一定的参考价值。

这是我的第一个Unity大型游戏项目,我试图使用静态方法调用协同程序来更改游戏状态和负载级别之间的更新调用。

从我所读到的这样的东西会起作用吗?

public class Game : MonoBehaviour {

  private static Game me = null;

  private IEnumerator LoadMap(int sceneIndex)
  {
    /*change game state to loading*/
    yield return null;
    Application.LoadLevel(sceneIndex);
    yield return null;
    /*change game state to playing*/
  }

  public static void StartNewGame()
  {
    /*settup new game*/
    me.StartCoroutine(me.LoadLevel(1));
  }

  void Awake()
  {
    me = this;
  }

}

我不得不重写几次,所以我只是休息一下,这次提前问。

答案

为了解决这个问题,我不得不将其分解为两部分。首先是通过静态方法调用Coroutines。 Unity默认情况下不允许调用Coroutines,但可以创建一个类来模拟此行为。 “StaticCoroutine”类允许用户使用内部存储的私有托管实例在静态方法中触发Coroutines。该脚本不需要场景依赖,因此无需将monobehaviour脚本添加到GameObject(除非您愿意)。要使用,只需创建一个名为“StaticCoroutine”的C#脚本,并在脚本中粘贴以下代码:

using System.Collections;
using UnityEngine;

public class StaticCoroutine : MonoBehaviour {
    private static StaticCoroutine m_instance;

    // OnDestroy is called when the MonoBehaviour will be destroyed.
    // Coroutines are not stopped when a MonoBehaviour is disabled, but only when it is definitely destroyed.
    private void OnDestroy()
    { m_instance.StopAllCoroutines(); }

    // OnApplicationQuit is called on all game objects before the application is closed.
    // In the editor it is called when the user stops playmode.
    private void OnApplicationQuit()
    { m_instance.StopAllCoroutines(); }

    // Build will attempt to retrieve the class-wide instance, returning it when available.
    // If no instance exists, attempt to find another StaticCoroutine that exists.
    // If no StaticCoroutines are present, create a dedicated StaticCoroutine object.
    private static StaticCoroutine Build() {
        if (m_instance != null)
        { return m_instance; }

        m_instance = (StaticCoroutine)FindObjectOfType(typeof(StaticCoroutine));

        if (m_instance != null)
        { return m_instance; }

        GameObject instanceObject = new GameObject("StaticCoroutine");
        instanceObject.AddComponent<StaticCoroutine>();
        m_instance = instanceObject.GetComponent<StaticCoroutine>();

        if (m_instance != null)
        { return m_instance; }

        Debug.LogError("Build did not generate a replacement instance. Method Failed!");

        return null;
    }

    // Overloaded Static Coroutine Methods which use Unity's default Coroutines.
    // Polymorphism applied for best compatibility with the standard engine.
    public static void Start(string methodName)
    { Build().StartCoroutine(methodName); }
    public static void Start(string methodName, object value)
    { Build().StartCoroutine(methodName, value); }
    public static void Start(IEnumerator routine)
    { Build().StartCoroutine(routine); }
}

我比使用Awake更喜欢这种方法,因为我只在需要时查询实例。每当我没有主动加载的实例时,我可以找到另一个(如果它存在),或者甚至用所需的脚本动态创建一个空白的GameObject。这就是为什么不需要改变场景,并且代码只是即插即用的原因。

问题的第二部分是通过Static Coroutines加载级别。请记住,Application.LoadLevel被认为是一种过时的方法,并被Unity的SceneManager取代。在这种情况下,最简单的级别更改可以按如下方式完成:

SceneManager.LoadScene("SceneNameHere", LoadSceneMode.Single);

这将用新的级别替换当前加载的级别。指数不适用于此,因此您需要场景名称才能进行转换。首选方法是使用LoadSceneAsync()来避免加载时出现暂停或性能问题。这个方法的Scripting Page有一个使用IEnumerator的实现,它与你的代码以及StaticCoroutine完全兼容。

以上是关于UnityScript,在FSM中使用协同程序的静态方法的主要内容,如果未能解决你的问题,请参考以下文章

Unity 中的 UnityScript 到 C#

UnityScript 中 Array.Unshift() 的 C# 版本?

Unityscript/Javascript 是不是已停产?

在 XState FSM 中使用外部数据

UnityScript中需要注意的问题

有限状态机(FSM)的Java 学习FSM