Unity StopCoroutine 当存在多层(或嵌套)“yield return”时不停止协程

KY *_* Lu 5 c# coroutine unity-game-engine

如果我使用 one-layer yield returnStopCoroutine()可以成功停止我的协程。请参阅下面的代码示例...

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestStopcoroutine : MonoBehaviour {
  IEnumerator co = null;

  // Use this for initialization
  void Start () {
    co = FunA();
    StartCoroutine(co);
  }

  private IEnumerator FunA() {
    Debug.Log("Enter FunA...");
    yield return RepeatPrint();
    Debug.Log("FunA end...");
  }

  private IEnumerator RepeatPrint() {
    for (int i = 0; i < 5; i++) {
      Debug.Log(i);
      yield return new WaitForSeconds(1);
    }
  }

  /// <summary>
  /// Set this function to a button on UI Canvas 
  /// </summary>
  public void OnCancelButtonClick() {
    if (co != null) {
      StopCoroutine(co);
      Debug.Log("Stop Coroutine...");
      co = null;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这个输出是...

// Enter FunA...
// 0
// 1
// 2
// 3
// Stop Coroutine...
Run Code Online (Sandbox Code Playgroud)

但是,如果我添加一层(即FunB()),FunA()将停止,但内部协程(FunB())不会停止。请参阅下面的示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestStopcoroutine : MonoBehaviour {
  IEnumerator co = null;

  void Start () {
    co = FunA();
    StartCoroutine(co);
  }

  private IEnumerator FunA() {
    Debug.Log("Enter FunA...");
    yield return FunB();
    Debug.Log("FunA end...");
  }

  private IEnumerator FunB () {
    Debug.Log("Enter FunB...");
    yield return RepeatPrint();
    Debug.Log("FunB end...");
  }

  private IEnumerator RepeatPrint() {
    for (int i = 0; i < 5; i++) {
      Debug.Log(i);
      yield return new WaitForSeconds(1);
    }
  }

  /// <summary>
  /// Set this function to a button on UI Canvas 
  /// </summary>
  public void OnCancelButtonClick() {
    if (co != null) {
      StopCoroutine(co);
      Debug.Log("Stop Coroutine...");
      co = null;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这个输出是...

// Enter FunA...
// Enter FunB...
// 0
// 1
// 2
// Stop Coroutine...
// 3
// 4
// FunB end...
Run Code Online (Sandbox Code Playgroud)

因此,我想知道为什么StopCoroutine()不能成功停止多层yield return协程?

KYL*_*L3R -1

协程彼此独立运行。因此,停止主协程不会影响任何其他已经启动的协程。

看来你有两个选择:

A:从第一层内部停止嵌套协程

  • 存储一个引用RepeatPrint并使用来使用 StopCoroutine 来停止它。

编辑:实际上“从第一级内部”是不必要的,只需使用正确的参考即可。

B:停止 MonoBehaviour 中的所有协程

  • 如果没有其他协程运行,可能会起作用