UnityUnityメモ

【完全解説】Unityの非同期処理!Coroutineとasync/awaitの違いと使い方

Unity

1. はじめに

Unityでゲームを開発していると、「非同期処理」という言葉を耳にすることがあるかもしれません。たとえば、「シーンのロード中にゲームをフリーズさせずに処理を続けたい」「Web APIからデータを取得して、結果が返ってくるまで待ちたい」といった場面で役立つのが非同期処理です。

しかし、Unityには非同期処理を実現する方法がいくつかあり、どれを使うべきか迷うこともあるでしょう。特に、Coroutine(コルーチン)async/await は、どちらも非同期処理を扱うための強力なツールですが、それぞれに得意・不得意があります。


この記事では、

  • Coroutine(コルーチン)とは? その基本と使い方
  • async/awaitとは? C#の非同期処理の仕組みとUnityでの使い方
  • Coroutineとasync/awaitの違い それぞれのメリット・デメリット
  • 実践例 Unityでの効果的な非同期処理の活用方法

を詳しく解説します。非同期処理をマスターすれば、スムーズなシーン遷移やデータ取得、エフェクト演出など、より洗練されたゲーム体験 を作ることができます。

それでは、さっそく非同期処理の基本から見ていきましょう!



2. 非同期処理とは?

ゲーム開発において、処理の流れ(フロー)をどのように制御するか は非常に重要です。特に、重い処理を適切に扱わないと、ゲームがカクついたり、一時的にフリーズしてしまうことがあります。この問題を解決する方法の一つが 非同期処理 です。


同期処理 vs 非同期処理

まずは、同期処理と非同期処理の違いを理解しましょう。

  • 同期処理(Synchronous Processing)
    処理を 順番に実行 する方式です。ある処理が完了しないと次の処理が始まりません。たとえば、ボタンを押してWebサーバーからデータを取得する場合、データの受信が完了するまでゲーム全体の処理が止まることになります。例(同期処理)csharpコピーする編集するvoid LoadData() { var data = GetDataFromServer(); // サーバーからデータ取得(時間がかかる) Debug.Log("データ取得完了: " + data); }この場合、GetDataFromServer() の処理が終わるまで、他の処理は一切進みません。
  • 非同期処理(Asynchronous Processing)
    処理を待たずに次の処理を進められる 方式です。たとえば、データの取得を別のスレッドで行い、その間に他の処理を進めることができます。これにより、ユーザーに対してスムーズな操作感を提供できます。例(非同期処理)csharpコピーする編集するasync void LoadDataAsync() { var data = await GetDataFromServerAsync(); // データ取得中でも他の処理が進行 Debug.Log("データ取得完了: " + data); }このコードでは、データ取得の待機中にゲームの他の部分は通常通り動作します。

Unityにおける非同期処理の活用例

Unityのゲーム開発では、次のような場面で非同期処理が役立ちます。

  1. シーンのロード
    • SceneManager.LoadSceneAsync() を使えば、ゲームをフリーズさせずに新しいシーンを読み込めます。
  2. Web APIからのデータ取得
    • UnityWebRequestasync/await を使えば、ネットワーク通信が完了するのを待ちながら、他の処理を続行できます。
  3. アセットのロード
    • AddressablesResources.LoadAsync() を使うことで、大きなアセットを読み込みながらゲームの進行を維持できます。
  4. スムーズなアニメーションや演出
    • Coroutine を使って、徐々に変化する動作(フェードイン・アウト、オブジェクトの移動など)を実現できます。

Unityにおける非同期処理の代表的な手法

Unityでは、主に Coroutine(コルーチン)async/await の2つの方法で非同期処理を実装できます。

非同期処理の種類特徴
CoroutineUnity独自の仕組みで、ゲームオブジェクトに依存する。フレーム単位で処理を分割できる。
async/awaitC#の標準的な非同期処理で、ネットワーク通信やファイル読み込みに向いている。

次のステップでは、それぞれの詳細な使い方を見ていきましょう!



3. Coroutine(コルーチン)とは?

コルーチン(Coroutine) は、Unity独自の非同期処理の仕組みで、特定の処理を 複数のフレームにまたがって少しずつ実行する ことができます。例えば、「一定時間ごとに敵をスポーンさせる」「徐々にオブジェクトを移動させる」などの処理を実装するときに便利です。


コルーチンの基本的な使い方

コルーチンを使うには、IEnumerator を返すメソッド を作成し、yield return を使って処理を分割します。

基本形

using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
void Start()
{
StartCoroutine(ExampleCoroutine()); // コルーチンの開始
}

IEnumerator ExampleCoroutine()
{
Debug.Log("3秒待機開始");
yield return new WaitForSeconds(3); // 3秒待機
Debug.Log("3秒経過後の処理");
}
}

解説

  1. IEnumerator を返すメソッド(ExampleCoroutine)を作成する。
  2. yield return new WaitForSeconds(3); で3秒間待機する。
  3. StartCoroutine(ExampleCoroutine()) を呼び出すことで、コルーチンが開始される。

このコードを実行すると、Start メソッドでコルーチンが開始され、3秒後に次の処理が実行 されます。


yield return の使い方

コルーチンでは、yield return を使って処理の実行を一時停止し、特定のタイミングで再開できます。

yield return の種類説明
yield return null;次のフレームまで待機する
yield return new WaitForSeconds(x);指定した秒数 x だけ待機する
yield return new WaitUntil(condition);conditiontrue になるまで待機する
yield return new WaitWhile(condition);conditionfalse になるまで待機する

例:一定時間ごとに処理を実行

IEnumerator RepeatAction()
{
while (true)
{
Debug.Log("1秒ごとに実行");
yield return new WaitForSeconds(1);
}
}

このコードを StartCoroutine(RepeatAction()) で呼び出すと、1秒ごとにログが出力 され続けます。


コルーチンを停止する方法

コルーチンを途中で止めたい場合は、StopCoroutine() または StopAllCoroutines() を使います。

コルーチンの停止

Coroutine coroutine;

void Start()
{
coroutine = StartCoroutine(ExampleCoroutine());
Invoke("StopMyCoroutine", 5); // 5秒後に停止
}

void StopMyCoroutine()
{
StopCoroutine(coroutine);
Debug.Log("コルーチンを停止しました");
}

StopCoroutine(coroutine); を実行すると、そのコルーチンが途中で終了します。

また、すべてのコルーチンを強制終了したい場合は StopAllCoroutines(); を使います。




コルーチンの実践例

例1:スムーズな移動処理

IEnumerator MoveObject(GameObject obj, Vector3 targetPosition, float duration)
{
Vector3 startPosition = obj.transform.position;
float elapsedTime = 0;

while (elapsedTime < duration)
{
obj.transform.position = Vector3.Lerp(startPosition, targetPosition, elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null; // 次のフレームまで待機
}

obj.transform.position = targetPosition; // 最終地点にセット
}

この関数を StartCoroutine(MoveObject(myObject, new Vector3(5, 0, 0), 2)); のように呼び出すと、myObject2秒かけてスムーズに移動 します。

例2:フェードイン・フェードアウト

IEnumerator FadeOut(CanvasGroup canvasGroup, float duration)
{
float elapsedTime = 0;
while (elapsedTime < duration)
{
canvasGroup.alpha = 1 - (elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null;
}
canvasGroup.alpha = 0;
}

StartCoroutine(FadeOut(myCanvasGroup, 1.5f)); のように呼び出すと、1.5秒かけてUIがフェードアウト します。


コルーチンのメリット・デメリット

✅ メリット

  • フレームごとに処理を分割できる ので、ゲームが止まらずスムーズに動作する。
  • 簡単に時間制御ができるWaitForSecondsWaitUntil など)。
  • スクリプトがシンプルになる (複雑な処理を段階的に書ける)。

❌ デメリット

  • ゲームオブジェクトが無効化されると、コルーチンが強制終了 する。
  • 戻り値を返せない(計算結果を受け取る処理には向いていない)。
  • スレッドを分けることはできない(CPUの負荷を分散する処理には向かない)。

まとめ

  • コルーチンはUnity独自の非同期処理 であり、フレーム単位で処理を分割できる。
  • yield return を使うことで、特定の時間待機したり、条件を満たすまで待つことができる。
  • スムーズな移動、エフェクト演出、時間制御 などに適している。
  • ただし、スレッドをまたぐような処理(ネットワーク通信や重い計算処理)には向かない。

次のステップでは、C#の標準的な非同期処理 async/await を解説していきます!




4. async/awaitとは?

async/await は、C#における非同期処理を記述するための仕組みです。
Unityでは、ネットワーク通信やファイルの読み込みなど、時間がかかる処理をスムーズに実行 するために使われます。


async/await の基本

同期処理(通常の処理)

通常のC#メソッドは、処理が完了するまで次の処理を待ちます。例えば、Web APIからデータを取得する処理 を同期的に書くと、次のようになります。

string LoadData()
{
// 仮のデータ取得処理(実際は時間がかかる)
System.Threading.Thread.Sleep(3000); // 3秒待つ
return "データを取得しました";
}

void Start()
{
string result = LoadData();
Debug.Log(result);
}

このコードでは、LoadData() が終わるまで 3秒間ゲームがフリーズ してしまいます。これでは、プレイヤーが操作できず、ストレスを感じてしまうでしょう。


async/await を使った非同期処理

ここで async/await を使うと、フリーズせずに処理を進めることができます。

using System.Threading.Tasks;
using UnityEngine;

public class AsyncExample : MonoBehaviour
{
async void Start()
{
string result = await LoadDataAsync(); // 非同期処理を実行
Debug.Log(result);
}

async Task<string> LoadDataAsync()
{
await Task.Delay(3000); // 3秒待機(スレッドをブロックしない)
return "データを取得しました(非同期)";
}
}

解説

  1. async Task<string> LoadDataAsync() のように asyncキーワード を付けてメソッドを作成。
  2. await Task.Delay(3000);3秒待機 するが、メインスレッドはブロックされない。
  3. await LoadDataAsync();処理を待ちながら、他の処理も並行して実行 できる。

このコードでは、LoadDataAsync() の完了を待っている間も、ゲームの他の処理は通常通り動き続けます!


async/await のメリット

メインスレッドをブロックしない → ゲームのフレーム更新が止まらない!
戻り値を扱えるTask<T> を使うことで、非同期処理の結果を受け取れる!
エラーハンドリングがしやすいtry-catch で例外をキャッチできる!




Unityでの async/await の活用例

Unityでは、次のような場面で async/await を使うことが多いです。

① Web API からデータ取得

using UnityEngine;
using UnityEngine.Networking;
using System.Threading.Tasks;

public class WebRequestExample : MonoBehaviour
{
async void Start()
{
string url = "https://jsonplaceholder.typicode.com/todos/1";
string result = await FetchDataAsync(url);
Debug.Log(result);
}

async Task<string> FetchDataAsync(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var operation = request.SendWebRequest();

while (!operation.isDone)
{
await Task.Yield(); // フレームをまたいで待機
}

if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("データ取得失敗: " + request.error);
return null;
}

return request.downloadHandler.text;
}
}
}

🔹 Web APIの応答を待ちながら、他の処理を進められる!
🔹 await Task.Yield(); を使うことで、ゲームのフリーズを防ぐ。


② ファイルの読み書き

using System.IO;
using System.Threading.Tasks;
using UnityEngine;

public class FileExample : MonoBehaviour
{
async void Start()
{
string path = Application.persistentDataPath + "/test.txt";

await WriteToFileAsync(path, "Hello, Unity!");
string content = await ReadFromFileAsync(path);
Debug.Log("ファイルの内容: " + content);
}

async Task WriteToFileAsync(string path, string content)
{
await File.WriteAllTextAsync(path, content);
}

async Task<string> ReadFromFileAsync(string path)
{
if (File.Exists(path))
{
return await File.ReadAllTextAsync(path);
}
return "ファイルが存在しません";
}
}

🔹 ファイルの入出力を非同期で処理できる!
🔹 大きなデータを扱ってもゲームが止まらない!


async/await と Coroutine(コルーチン)の違い

比較項目Coroutine(コルーチン)async/await
Unity独自の機能✅ あり❌ なし
スレッドの分割❌ できない✅ 可能
戻り値の受け取り❌ 不可 (IEnumerator は値を返さない)✅ 可能 (Task<T> で受け取れる)
エラーハンドリング❌ 例外処理が難しいtry-catch で簡単
フレーム単位の制御✅ 可能 (yield return)❌ 不可
用途シーン遷移、アニメーション制御などネットワーク通信、ファイル入出力など

async/await のデメリット

Unityのメインスレッドと連携しにくい
await を使うと、別スレッドで処理されるため、UnityのGameObjectやUIに直接アクセスするとエラーになることがある。

解決策: UnityMainThreadDispatcher を使う or Task.Yield() を活用!

await Task.Yield(); // メインスレッドに戻る

ゲームオブジェクトが破棄されると処理が続く可能性
CancellationToken を使うと安全に中断できる。


まとめ

  • async/awaitC#の非同期処理の仕組み であり、スレッドを分けて処理ができる。
  • ネットワーク通信やファイル入出力に適している
  • Task<T> を使えば非同期処理の結果を受け取れる ため、柔軟なプログラムが可能。
  • エラーハンドリングが簡単(try-catch が使える)
  • Unityのメインスレッドと連携する際は注意が必要Task.Yield() などを活用)。

次のステップでは、Coroutineとasync/awaitの具体的な違いと、どちらを使うべきかを詳しく解説 していきます!




5. Coroutineとasync/awaitの違い

Unityの非同期処理を実装する際、Coroutine(コルーチン)async/await のどちらを使うべきか迷うことがあるでしょう。それぞれの特徴や使い分けを理解することで、最適な選択ができるようになります。


Coroutineとasync/awaitの基本的な違い

項目Coroutine(コルーチン)async/await
主な用途Unity内のフレーム単位の処理(アニメーション、時間制御)スレッドをまたぐ処理(ネットワーク通信、ファイル操作)
Unityのメインスレッド✅ 維持される(GameObject操作OK)❌ 別スレッドになる場合あり(GameObject操作NGのケースあり)
戻り値の受け取り❌ できない (IEnumerator は値を返さない)Task<T> で結果を取得可能
エラーハンドリング❌ 例外処理が難しい (try-catch が使えない)try-catch で簡単に例外処理ができる
スレッドの使用❌ できない(メインスレッドのみ)✅ 可能(バックグラウンドスレッドで処理できる)
パフォーマンス軽い(メインスレッド上で実行)スレッド処理が可能だが、状況によってはオーバーヘッドが発生
用途シーン遷移、アニメーション、エフェクト、敵のスポーンなどAPIリクエスト、ファイル入出力、重い計算処理など

どちらを使うべき?用途ごとの選択基準

Coroutine を使うべきケース

  1. フレーム単位の制御が必要な場合
    • yield return を使って フレームごとに処理を分割 できるため、アニメーションや時間制御に向いている。
    • 例: オブジェクトの移動、フェードイン/アウト、敵のスポーン
  2. UnityのGameObjectを直接操作する場合
    • async/await では バックグラウンドスレッドに移動する可能性 があるため、GameObjectやUIの操作には向いていない。
  3. 簡単な待機処理
    • yield return new WaitForSeconds(2); で簡単に時間待機ができる。

async/await を使うべきケース

  1. 重い処理をバックグラウンドで実行したい場合
    • Task.Run(() => { }) を使えば、CPUをブロックせずに重い処理を並行実行 できる。
    • 例: 画像の解析、AI計算、大量データ処理
  2. 非同期のAPI通信
    • UnityWebRequestHttpClientサーバーからデータを取得する際に、処理の完了を待ちつつ他の処理を続行 できる。
  3. ファイルの読み書き
    • File.ReadAllTextAsync()File.WriteAllTextAsync() など、C#の 非同期ファイル操作を活用 したい場合に適している。



実際の使い分け例

【Coroutineを使う場合】オブジェクトを滑らかに移動

IEnumerator MoveObject(GameObject obj, Vector3 target, float duration)
{
Vector3 start = obj.transform.position;
float elapsedTime = 0;

while (elapsedTime < duration)
{
obj.transform.position = Vector3.Lerp(start, target, elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null; // 次のフレームまで待機
}

obj.transform.position = target;
}

メリット

  • yield return null; を使って 毎フレーム更新 できるため、スムーズな動作が可能。
  • メインスレッドで実行されるため、GameObjectの操作に問題がない。

【async/awaitを使う場合】Web API からデータ取得

using UnityEngine;
using UnityEngine.Networking;
using System.Threading.Tasks;

public class WebRequestExample : MonoBehaviour
{
async void Start()
{
string url = "https://jsonplaceholder.typicode.com/todos/1";
string result = await FetchDataAsync(url);
Debug.Log(result);
}

async Task<string> FetchDataAsync(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var operation = request.SendWebRequest();

while (!operation.isDone)
{
await Task.Yield(); // フレームをまたいで待機
}

if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("データ取得失敗: " + request.error);
return null;
}

return request.downloadHandler.text;
}
}
}

メリット

  • サーバーの応答を待つ間に他の処理を進められる!
  • Task.Yield(); を使えば フレームごとに処理を進められるため、パフォーマンスを確保できる!

Coroutine と async/await の組み合わせ

場合によっては、両者を組み合わせることで、より柔軟な非同期処理 が可能になります。

【組み合わせ例】非同期のWeb API通信をコルーチンで待機

IEnumerator FetchDataAndDisplay()
{
Task<string> task = FetchDataAsync("https://example.com/api");
yield return new WaitUntil(() => task.IsCompleted); // タスク完了まで待機

Debug.Log("取得したデータ: " + task.Result);
}

async Task<string> FetchDataAsync(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var operation = request.SendWebRequest();
while (!operation.isDone)
{
await Task.Yield();
}

if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("データ取得失敗: " + request.error);
return null;
}

return request.downloadHandler.text;
}
}

メリット

  • Web APIのデータ取得は async/await で処理
  • コルーチンでタスクの完了を待機し、メインスレッドで安全に処理

まとめ

どちらを使うべき?

Coroutine

  • シーン遷移やアニメーション、エフェクトなど、フレームごとに処理したいとき
  • yield return時間制御を簡単にしたいとき
  • UnityのGameObjectを操作する場合

async/await

  • ネットワーク通信やファイルの読み書き など、スレッドをまたぐ処理 に向いている
  • Task<T> を使って 非同期処理の結果を受け取りたいとき
  • try-catch でエラーハンドリングを簡単にしたいとき

組み合わせることで、より高度な非同期処理が可能に!
次のステップでは、実践的な活用例を紹介していきます!




6. 実践!非同期処理の活用例

ここまでで Coroutine(コルーチン)async/await の違いや特徴を学びました。
このセクションでは、Unityのゲーム開発で役立つ 実践的な非同期処理の活用例 を紹介します!


① シーン遷移をスムーズに行う(Coroutine)

ゲームのシーンをロードするときに、一瞬画面が止まる 経験をしたことはありませんか?
SceneManager.LoadScene() をそのまま使うと、シーンの読み込みが終わるまでゲームがフリーズ してしまいます。

✅ 解決策:非同期ロードを行う

Unityの LoadSceneAsync()コルーチン を使ってスムーズに処理しましょう!

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

public class SceneLoader : MonoBehaviour
{
public void LoadNewScene()
{
StartCoroutine(LoadSceneCoroutine("GameScene"));
}

IEnumerator LoadSceneCoroutine(string sceneName)
{
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
operation.allowSceneActivation = false; // すぐにシーンを切り替えない

while (!operation.isDone)
{
Debug.Log("読み込み進行度: " + (operation.progress * 100) + "%");

// 読み込みが90%を超えたらシーンを切り替える
if (operation.progress >= 0.9f)
{
operation.allowSceneActivation = true;
}
yield return null;
}
}
}

メリット

  • SceneManager.LoadSceneAsync() を使って ゲームをフリーズさせずにシーンをロード
  • 読み込み進行度を表示 できるので、ロード画面を作成しやすい

② Web APIからデータを取得する(async/await)

ネットワーク通信を行う際、APIのレスポンス待ちでゲームが止まらないように するには、async/await を活用しましょう。

✅ Web APIからデータを取得

using UnityEngine;
using UnityEngine.Networking;
using System.Threading.Tasks;

public class APIClient : MonoBehaviour
{
async void Start()
{
string url = "https://jsonplaceholder.typicode.com/todos/1";
string data = await FetchDataAsync(url);
Debug.Log("取得したデータ: " + data);
}

async Task<string> FetchDataAsync(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var operation = request.SendWebRequest();

while (!operation.isDone)
{
await Task.Yield(); // フレームをまたいで待機
}

if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("データ取得失敗: " + request.error);
return null;
}

return request.downloadHandler.text;
}
}
}

メリット

  • APIのレスポンスを待ちながら、他の処理を進められる
  • データ取得後に処理を続けることができる



③ オブジェクトをスムーズに動かす(Coroutine)

オブジェクトを 一定時間かけて移動 したい場合、コルーチンを使うとスムーズに処理できます。

✅ オブジェクトの移動アニメーション

IEnumerator MoveObject(GameObject obj, Vector3 target, float duration)
{
Vector3 start = obj.transform.position;
float elapsedTime = 0;

while (elapsedTime < duration)
{
obj.transform.position = Vector3.Lerp(start, target, elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null; // 次のフレームまで待機
}

obj.transform.position = target;
}

🔹 Lerp を使って、開始地点から目的地へ徐々に移動 するアニメーションを実装!
🔹 yield return null; を使って、毎フレームごとに少しずつ処理 する。


④ 重い計算処理をバックグラウンドで実行(async/await)

AIの計算や画像処理など、CPU負荷の高い処理 をメインスレッドで実行すると、ゲームがカクついてしまいます。
Task.Run() を使って、別スレッドで計算処理 を行いましょう。

✅ 重い計算処理を非同期で実行

using System;
using System.Threading.Tasks;
using UnityEngine;

public class HeavyCalculation : MonoBehaviour
{
async void Start()
{
int result = await RunHeavyTask();
Debug.Log("計算結果: " + result);
}

async Task<int> RunHeavyTask()
{
return await Task.Run(() =>
{
int sum = 0;
for (int i = 0; i < 100000000; i++)
{
sum += i;
}
return sum;
});
}
}

メリット

  • Task.Run() を使って メインスレッドをブロックせずに計算
  • await処理完了後に結果を受け取る

⑤ ファイルを非同期で読み書き(async/await)

ゲームデータの保存・読み込みを行う際に、同期処理だとゲームが止まる 可能性があります。
File.ReadAllTextAsync() を使って、スムーズなデータ処理 を実装しましょう。

✅ 非同期でファイルの読み書き

using System.IO;
using System.Threading.Tasks;
using UnityEngine;

public class FileHandler : MonoBehaviour
{
async void Start()
{
string path = Application.persistentDataPath + "/test.txt";

await WriteToFileAsync(path, "Hello, Unity!");
string content = await ReadFromFileAsync(path);
Debug.Log("ファイルの内容: " + content);
}

async Task WriteToFileAsync(string path, string content)
{
await File.WriteAllTextAsync(path, content);
}

async Task<string> ReadFromFileAsync(string path)
{
if (File.Exists(path))
{
return await File.ReadAllTextAsync(path);
}
return "ファイルが存在しません";
}
}

メリット

  • ファイルの読み書きを待ちながら、他の処理を継続できる
  • await を使って 処理完了後にデータを取得

まとめ

🔥 実践的な非同期処理の活用法 🔥

ケース使うべき手法
シーン遷移をスムーズにCoroutine + SceneManager.LoadSceneAsync()
Web API からデータ取得async/await + UnityWebRequest
オブジェクトのアニメーションCoroutine + Lerp()
重い計算を非同期で実行async/await + Task.Run()
ファイルの非同期読み書きasync/await + File.ReadAllTextAsync()

Unityでは 「フレーム単位の処理」なら Coroutine、「スレッドをまたぐ処理」なら async/await が適しています!
次のステップでは、よくある質問(FAQ) を解説していきます!




よくある質問(FAQ)

Q
Coroutineとasync/awaitを同時に使うことはできる?
A

可能です!
それぞれ得意な処理が異なるため、適切に使い分けることでより効率的なコードが書けます。

例えば、Web API からデータを取得する部分は async/await を使い、そのデータを使って UI を更新する部分は Coroutine を使う というように、組み合わせることができます。

例:async/await でデータを取得し、Coroutine でUIをフェードイン

IEnumerator FadeIn(CanvasGroup canvasGroup, float duration)
{
float elapsedTime = 0;
while (elapsedTime < duration)
{
canvasGroup.alpha = elapsedTime / duration;
elapsedTime += Time.deltaTime;
yield return null;
}
canvasGroup.alpha = 1;
}

async void Start()
{
string data = await FetchDataAsync("https://example.com/api");
Debug.Log("データ取得完了: " + data);
StartCoroutine(FadeIn(GetComponent<CanvasGroup>(), 1f)); // UIをフェードイン
}
Q
async/awaitはUnityのメインスレッドをブロックしないの?
A

基本的にはブロックしません。
async/await非同期処理をスレッドで分けて実行 できるため、重い処理を実行してもゲームが止まることはありません。

ただし、Task.Run() を使うとバックグラウンドスレッドで処理されるため、UnityのGameObjectやUIを直接変更するとエラーになる ことがあります。

解決策:Unityのメインスレッドに戻る

async Task UpdateUIAsync(string text)
{
await Task.Yield(); // メインスレッドに戻る
myTextComponent.text = text; // UI更新
}
Q
Task.Run() を使えばUnityのパフォーマンスは向上する?
A

ケースによります。
Task.Run() を使うと CPU処理を別スレッドで実行 できるため、重い計算処理(例:AIの処理、大量データの計算) では有効です。

しかし、UnityのGameObjectやコンポーネントの操作には使えません!
GameObjectの操作はメインスレッドで実行される必要があるため、Task.Run() を使うとエラーになることがあります。

Task.Run() が適しているケース

  • 画像や音声データの処理
  • 大量の計算(例:経路探索アルゴリズム)
  • ファイルの圧縮・展開
タイトルとURLをコピーしました