【Unity】Coroutineの正しい使い方とハマりがちな罠まとめ《後編》

当ブログではアフィリエイト広告を含みます
Unity

前編では、Coroutineの基本と使い方、そして罠1(止め方の落とし穴)について解説しました。
後編では、さらに「一見うまく動いてるように見えるけど、実はヤバい」タイプの罠を掘り下げていきます。

特に、ゲームが複雑になってくる中級開発者ほどやらかしやすい内容も含まれていますので、ぜひチェックを!

【罠2】WaitForSecondsは時間に厳密じゃない

WaitForSeconds(3) と書いたら3.000秒後に実行されると思っていませんか?
実際には「3秒くらい経った次のフレーム更新時」に再開されます。

さらに、Time.timeScale の影響も受けます。

たとえばポーズ中に Time.timeScale = 0f; にしていると…

IEnumerator WaitExample()
{
    yield return new WaitForSeconds(2f);  //2秒待つ
    Debug.Log("…が、これはポーズ中だと一生来ない👻");
}

↑ このログ、ポーズ中は絶対に表示されません!

✅ 対策:リアル時間で待ちたいときはこう書く

IEnumerator WaitRealTime(float sec)
{
    float end = Time.realtimeSinceStartup + sec;
    while (Time.realtimeSinceStartup < end)
        yield return null;
}

これなら Time.timeScale = 0 の影響を受けず、確実に実時間で処理が進みます。
タイトル画面やポーズメニューなど、ゲームが止まってても「裏で待ちたい処理」に便利。

【罠3】StartCoroutineを何度も呼んで暴走

こんなコード、書いたことありませんか?

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        StartCoroutine(BlinkText());
    }
}

スペースキーを連打すると、コルーチンが何本も同時に実行されてカオスになります。
テキストが高速で点滅し、場合によっては処理落ちします。

✅ 対策:既存のCoroutineを止めてから新しく始める

Coroutine blinkRoutine;

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        if (blinkRoutine != null)  //blinkRoutineがnullではないなら
            StopCoroutine(blinkRoutine);  //先に止めておく

        blinkRoutine = StartCoroutine(BlinkText());
    }
}

1つのCoroutineを変数で管理することで、暴走を防げます。
アニメ演出・UI制御などでよく使うテクニックです。

【罠4】IEnumeratorをnewで生成してStartCoroutineしない

C#的には書けるけど、Unity的にはアウトな書き方として紹介しておきます。

IEnumerator routine = new MyRoutine(); // コンパイルは通る
// でもこれはStartCoroutineされていない!

この場合、IEnumeratorの中身は呼ばれても、Unityの実行ループに乗らないので、
yield return が無視されて、MyRoutine() の処理内容が一気に最後まで実行されてしまいます。

✅ 正しくはこう!

StartCoroutine(MyRoutine());

StartCoroutine()を必ず通すこと!
Unityの内部でちゃんと「次のフレームで再開」が管理されるようになります。

【罠5】UIボタンやUnityEventからIEnumeratorを直接呼ぶ

これも超あるあるです。

public IEnumerator DoSomething()
{
    yield return new WaitForSeconds(1f);
    Debug.Log("呼ばれたけど、これはコルーチンじゃない!");
}

UnityのUIイベントに DoSomething() を直接登録すると、IEnumeratorとして認識されず、即終了します。

✅ 対策:呼び出し元の関数で StartCoroutine を呼ぶ

public void StartDoSomething()
{
    StartCoroutine(DoSomething());
}

UIイベントには StartDoSomething() を登録して、その処理として StartCorutine しましょう。

まとめ:コルーチンは動いてても油断禁物!

コルーチンは一見動いてるように見えるからこそ、バグや非意図的な挙動に気付きにくいのが怖いところ。

でも、正しく使えば本当に強力な味方になります!

✅ おさらいチェック

  • WaitForSecondsはTimeScaleに注意
  • 同じ処理を何度もStartCoroutineしないように管理
  • newしてIEnumeratorを動かそうとしない
  • UIイベントなどから直接IEnumeratorを呼ばない

このあたりを意識するだけで、「なんかおかしいな…」という不安が激減します。
「なんか動かない…」→「いや、StartCoroutine通してなかったわ」の事故、なくしていきましょう!

タイトルとURLをコピーしました