当布尔值为真时如何调用 IEnumerator?

How can I call IEnumerator when a boolean is true?

我正在使用 IEnumerator 函数,但我的 if 语句在工作时遇到了一些问题:

IEnumerator Spawning()
    {
        Debug.Log("Spawning being called...");
        if (GameObject.Find("FPSController").GetComponent<BoxCollide>().hitTrigger == true)
        {
            Debug.Log("CUSTOMER SHOULD SPAWN!");
            while (countStop == false) {

                yield return new WaitForSeconds(2);
                Debug.Log("Fisher Spawned!");
                counter++;
                spawnNewCharacter.SpawnCharacter();

                if (counter >= 3){
                    countStop = true;
                }

            }
        }
    }

经过一些调试,事实证明我的 if 语句确实有效。这个问题实际上是 IEnumerator 函数在我 运行 我的游戏时被调用。我需要一种方法来仅在我的 hitTrigger == true 时调用此 IEnumerator 函数,但我似乎无法正常工作。

我已经在 IEnumerator 函数之上尝试了这个:

void Update()
    {
        if (GameObject.Find("FPSController").GetComponent<BoxCollide>().hitTrigger == true)
        {
            Debug.Log("Spawning now...");
            StartCoroutine(Spawning());
        }
    } 

但仍然无法让 Debug.Log 中的任何一个通过。希望能提供一些帮助!

辅助信息

Find() 和 GetComponent()

您不想在 Update 方法中使用 GameObject.Find(...),因为这是一个开销很大的调用。 Update 方法每帧调用一次,因此您将在 1 秒内以 60fps 调用 60 次 GameObject.Find(...) 。 因此,当您使用 GetComponent() 或 Find() 时,您希望保存对这些对象的引用,如下面的代码片段所示。

使用 GetComponent() 或 GameObject.Find() 等方法的更好位置是 Awake() and Start() 方法。

清醒

Awake is used to initialize any variables or game state before the game starts. Awake is called only once during the lifetime of the script instance. Awake is called after all objects are initialized so you can safely speak to other objects or query them using eg. GameObject.FindWithTag. [...] Explanation is taken from the linked documentation.

开始

Start is called on the frame when a script is enabled just before any of the Update methods is called the first time. Like the Awake function, Start is called exactly once in the lifetime of the script. However, Awake is called when the script object is initialised, regardless of whether or not the script is enabled. Start may not be called on the same frame as Awake if the script is not enabled at initialisation time. Explanation is also taken from the linked documentation


可能的解决方案

将第一个组件 (FPSControllerCollission) 添加到包含 FPSController 的对象上。 它使用统一 OnTriggerEnter & OnTriggerExit 方法。

当触发器进入盒子碰撞器的 space 时,此脚本会将 IsTriggered 布尔值设置为 true

Note: A collider acts as a trigger, when the "Is Trigger" checkbox on the component is checked.

当碰撞器进入盒子碰撞器的space时,你可以用OnCollisionEnter/Exit来识别。

Note that the following is only an example and you'll have to tweak / integrate it into your code

  [RequireComponent(typeof(BoxCollider))]
  public class FPSControllerCollission : MonoBehaviour {
    public bool IsTriggered;

    private void OnTriggerEnter(Collider other) {
      this.IsTriggered = true;
    }

    private void OnTriggerExit(Collider other) {
      //Maybe check the tag/type of the other object here
      this.IsTriggered = false;
    }
  }

以下 SpawnController class 可以集成到您已经拥有的 class 中。

  public class SpawnController : MonoBehaviour {
    private FPSControllerCollission _fpsControllerCollission;

    private void Awake() {
      this._fpsControllerCollission = FindObjectOfType<FPSControllerCollission>();
    }

    private void Update() {
      if (this._fpsControllerCollission.IsTriggered) {
        StartCoroutine(nameof(Spawning));
      }
    }

    IEnumerator Spawning() {
      Debug.Log("Spawning being called...");
      if (this._fpsControllerCollission == true) {
        Debug.Log("CUSTOMER SHOULD SPAWN!");
        bool countStop = false;
        int counter;
        while (countStop == false) {

          yield return new WaitForSeconds(2);
          Debug.Log("Fisher Spawned!");

          counter++;
          spawnNewCharacter.SpawnCharacter();

          if (counter >= 3) {
            countStop = true;
          }

        }
      }
    }
  }