【Unity】コルーチン vs async/await - Unityの非同期処理はどっちを使う?

作成: 2026-07-05最終更新: 2026-07-13

「待つ処理」を書くとき、コルーチンとasync/awaitのどちらを使うべきか——Unity開発の定番の悩みを整理します。両者の仕組みの違い、使い分けの基準、Unity 6のAwaitable、破棄済みオブジェクト問題まで解説します。

「3秒待ってから爆発させたい」「ロードが終わったら画面を切り替えたい」——“待つ処理”を書こうとして検索すると、コルーチンで書く例と async/await で書く例の両方が出てきて、「結局どっちを使えばいいの?」と手が止まる。Unity開発で誰もが一度は通る分かれ道です。

結論から言うと、両者は競合ではなく、得意分野が違う道具です。この記事では仕組みの違いをイメージで掴み、迷わず選べる使い分け基準、Unity 6で加わった公式のAwaitable、そしてasync特有の落とし穴(破棄されたオブジェクト問題)までを整理します。

2つの非同期処理のイメージ。2本の道が並走している

この記事でわかること

  • コルーチン(フレーム駆動)とasync/await(完了待ち駆動)の仕組みの違い
  • 「演出はコルーチン、IO・通信はasync」という使い分けの理由
  • Unity 6の公式Awaitableでできること
  • asyncの落とし穴:破棄されたオブジェクトで処理が続く問題とdestroyCancellationToken

Sponsored

2つの仕組みをイメージで掴む

まず、両者が「待ち」をどう実現しているかをイメージで比べます。

コルーチンとasync/awaitの仕組みの比較図。コルーチンは毎フレーム発車する列車に乗って駅ごとに少しずつ進み、async/awaitは作業を別の担当者に依頼して完了の連絡を待つ

コルーチンは「フレームの列車」に乗る仕組みです。yield returnのたびに処理を中断し、次のフレーム(あるいは指定した条件のフレーム)で続きから再開します。Unityのゲームループに完全に同期して進むため、「毎フレーム少しずつフェードさせる」のようなフレーム単位の演出と好相性です。詳しい書き方は コルーチンの記事 で解説しています。

async/awaitは「担当者に依頼して完了を待つ」仕組みです。awaitした処理(ファイル読み込み、通信、アセットのロードなど)が終わるまでメソッドの続きが保留され、完了したら再開します。フレームとは無関係に「仕事が終わったかどうか」で進むのが特徴です。

// 同じ「1秒待ってから表示」を2通りで書くと——

// コルーチン版:フレームの列車に乗る
IEnumerator ShowAfterOneSecond()
{
    yield return new WaitForSeconds(1f);
    panel.SetActive(true);
}

// async/await版(Unity 6のAwaitable使用):完了を待つ
async Awaitable ShowAfterOneSecondAsync()
{
    await Awaitable.WaitForSecondsAsync(1f);
    panel.SetActive(true);
}

この例だけ見ると同じに見えますが、得意分野の差は「何を待つか」が複雑になるほど開いていきます。

コルーチンが向いている場面

ゲーム内の時間・フレームに紐づく処理はコルーチンの領分です。

コルーチンが向いている3つの場面の図。フェードなどの演出、yieldでフレームに同期する処理、オブジェクトの破棄と連動して自動で止まる処理
  • 演出: フェードイン、点滅、ノックバック、カメラシェイクなど「毎フレーム少しずつ」系
  • フレーム同期が必要な処理: yield return nullで1フレーム待つ、WaitForFixedUpdateで物理更新を待つ
  • GameObjectの寿命と運命を共にしたい処理: コルーチンはGameObjectが破棄されると自動で止まるため、後始末を考えなくていい

3つ目が地味に重要です。敵の点滅演出中にその敵が倒されても、コルーチンなら勝手に止まってくれます。

async/awaitが向いている場面

「ゲームの外」の仕事の完了を待つ処理はasync/awaitの領分です。

async/awaitが向いている3つの場面の図。セーブデータの読み書き、ネットワーク通信、アセットのロード——いずれもゲームの外の仕事の完了を待つ処理
  • ファイルの読み書き: セーブデータの非同期保存・読み込み
  • ネットワーク通信: ランキングの取得、APIの呼び出し
  • アセットのロード: AddressablesのLoadAssetAsyncは、返ってくるハンドルのTaskプロパティをawait handle.Taskの形で待てる
  • 戻り値が欲しい非同期処理: コルーチンは値を返せないが、async Task<T>async Awaitable<T>結果を返せる
using UnityEngine;

public class SaveService : MonoBehaviour
{
    // 戻り値を返せるのがasyncの強み(コルーチンにはできない)
    public async Awaitable<string> LoadRankingAsync()
    {
        await Awaitable.WaitForSecondsAsync(0.5f); // 通信の代わりのダミー待機
        return "1位: 12000点";
    }
}

「完了に何フレームかかるか分からない仕事を待ち、結果を受け取って続きをする」——この形が出てきたらasyncの出番です。

Sponsored

Unity 6の公式サポート:Awaitable

かつて「Unityでasync/awaitはひと工夫必要」と言われた理由は、コルーチンのyield returnに相当する公式の待機部品がなかったからです。Unity 6(2023.1以降)では Awaitable クラスが標準搭載され、この差がほぼ埋まりました。

やりたいことコルーチンasync/await(Awaitable)
秒数を待つyield return new WaitForSeconds(1f)await Awaitable.WaitForSecondsAsync(1f)
1フレーム待つyield return nullawait Awaitable.NextFrameAsync()
物理更新を待つyield return new WaitForFixedUpdate()await Awaitable.FixedUpdateAsync()
フレーム描画の最後まで待つyield return new WaitForEndOfFrame()await Awaitable.EndOfFrameAsync()

書き味が揃ったことで、「asyncで統一したい派」も公式機能だけで実現しやすくなりました。とはいえ次の注意点を知るまでは、安易な全面移行はおすすめしません。

注意点:asyncはオブジェクトが死んでも走り続ける

コルーチンとasyncの最大の性格の違いがここです。コルーチンはGameObjectの破棄で自動停止しますが、asyncメソッドは止まりません

コルーチンとasyncの寿命の違いの図。GameObjectが破棄されるとコルーチンは一緒に止まるが、asyncメソッドは破棄後も走り続けて、消えたオブジェクトを触ろうとしてエラーになる

シーン遷移や敵の撃破でオブジェクトが消えたあともawaitの続きが実行され、破棄済みのコンポーネントに触ってエラー——これがasync移行時の定番バグです。対策は、MonoBehaviourが標準で持つ destroyCancellationToken を渡すことです。

using UnityEngine;

public class ExplosionTimer : MonoBehaviour
{
    async void Start()
    {
        // このGameObjectが破棄されたら、待機ごとキャンセルされる
        await Awaitable.WaitForSecondsAsync(3f, destroyCancellationToken);

        Explode(); // 破棄済みなら、ここには到達しない
    }

    private void Explode()
    {
        Debug.Log("爆発!");
    }
}

補足: キャンセルされたawaitは例外(OperationCanceledException)で中断されます。async voidの最上位まで届いた例外はUnityエンジンが受け取り、Consoleにログとして出力されます(静かに消えるわけではありません)。キャンセルを「正常な終了」として扱いたい場合はtry-catchOperationCanceledExceptionを受け止めるのが確実です。ここが「コルーチンより一段むずかしい」と言われる所以です。

Sponsored

おまけ:先に知っておくと良いこと

使い分けの土台ができたら、次はこのあたりが視野に入ってきます。

  • コルーチンの基本を固める: yield returnの種類や止め方は コルーチンの記事 で整理できます。本記事の前提です。
  • 実戦の定番ライブラリ UniTask: コミュニティ製のUniTaskは、Awaitable登場以前からUnityのasyncを支えてきた定番です。GC負荷ゼロの待機や豊富な演算子など、公式より強力な部分も多く、asyncを本格採用するなら一見の価値があります。
  • asyncが本領を発揮するロード処理: シーンやアセットの非同期ロードは相性抜群の応用先です。SceneManagerの記事 のLoadSceneAsyncや Addressables入門 が実践の場になります。

まとめ

コルーチンとasync/awaitは、どちらが新しい・偉いではなく役割が違う道具です。

  • コルーチン: フレームの列車に乗る仕組み。演出・フレーム同期・GameObjectと寿命を共にする処理に。破棄で自動停止が強み。
  • async/await: 完了待ち駆動の仕組み。ファイルIO・通信・アセットロード・戻り値が欲しい処理に。
  • Unity 6のAwaitable で、秒待ち・フレーム待ちなどコルーチン相当の待機がasyncでも公式に書けるようになった。
  • asyncは破棄後も走り続けるdestroyCancellationTokenでキャンセルを仕込むのが鉄則。
  • 両者は併用してよい。「ゲーム内の時間はコルーチン、ゲーム外の仕事はasync」から始めるのが現実的。

どちらか一方を覚えて満足せず、「この待ちはフレームの話か、仕事の完了の話か?」と問いかける癖をつければ、迷いは消えていきます。