Unity の IEnumerator を返すメソッドの override

Unity には StartCoroutine というメソッドがあり、これは IEnumerator を引数にとって、非同期実行(別スレッドではない)ができるすごいやつである。

詳しくは公式サイト

これは一見魔法のように動作するが、その実仕組みはとても単純で、やっていることは、下記コードとほぼ同等である。

void Start() {
  myEnumerator = GetMyEnumerator();
}

void Update() {
  myEnumerator.MoveNext();
}

Coroutine の実行タイミングが気持ち悪い人間は、Update で自力で回せばいいと思う。

さて、Coroutine は便利な仕組みだが、継承すると、やや厄介な問題が生じる。親が IEnumerator なので、そのまま返すわけにはいかないのだ!

override IEnumerator GetMyEnumerator() {
  yield return base.GetMyEnumerator();
  yield return someValue:
}

これは期待通りに動作しない。親の IEnumerator もすべて回すには、StartCoroutine を使う必要がある。

override IEnumerator GetMyEnumerator() {
  yield return StartCoroutine(base.GetMyEnumerator());
  yield return someValue:
}

しかし、これは MonoBehaviour を継承してないときに困る。 MonoBehaviour を継承していないときは、最初の Update の例のように自力で回せば良い。

override IEnumerator GetMyEnumerator() {
  var baseEnumerator = base.GetMyEnumerator();
  while (baseEnumerator.MoveNext()) {
    yield return baseEnumerator.Current;
  }
  yield return someValue:
}