Unity-Coroutineとは？超基本的な解説

# Unityのコルーチンとは？超基本から解説

Unityのコルーチン（Coroutine）は、時間経過を伴う処理を簡単に実装できる機能です。通常の関数は一度呼び出されるとすぐに終了しますが、コルーチンを使うと**処理を一時停止しながら、複数のフレームにわたって実行**できます。

## 1. コルーチンの基本

### コルーチンの定義方法
コルーチンは `IEnumerator` 型のメソッドとして定義し、`yield return` を使って処理を途中で止められます。

```csharp
using System.Collections;
using UnityEngine;

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

    IEnumerator MyCoroutine()
    {
        Debug.Log("処理開始");
        yield return new WaitForSeconds(2); // 2秒待つ
        Debug.Log("2秒後に再開");
    }
}
```

### コルーチンの特徴
- `IEnumerator` を返すメソッドとして定義
- `yield return` で処理を一時停止できる
- `StartCoroutine()` で開始
- **非同期的に動作し、フレームごとに処理を継続**

## 2. `yield return` の使い方

`yield return` を使うことで、処理を一定時間待機したり、次のフレームまで待つことができます。

### 代表的な `yield return`
| コード | 説明 |
|--------|------|
| `yield return null;` | **次のフレームまで待機** |
| `yield return new WaitForSeconds(秒数);` | **指定した時間だけ待機** |
| `yield return new WaitForEndOfFrame();` | **フレームの描画が終わるまで待機** |
| `yield return new WaitForFixedUpdate();` | **次の `FixedUpdate()` まで待機** |

**例：フレームごとに処理を実行するコルーチン**
```csharp
IEnumerator CountCoroutine()
{
    for (int i = 0; i < 5; i++)
    {
        Debug.Log("カウント: " + i);
        yield return null; // 次のフレームまで待機
    }
}
```

## 3. コルーチンの停止

コルーチンを停止するには `StopCoroutine()` または `StopAllCoroutines()` を使用します。

```csharp
Coroutine runningCoroutine;

void Start()
{
    runningCoroutine = StartCoroutine(MyCoroutine());
}

void StopMyCoroutine()
{
    if (runningCoroutine != null)
    {
        StopCoroutine(runningCoroutine);
    }
}
```

- **`StopCoroutine(コルーチン名)`** → 特定のコルーチンを停止
- **`StopAllCoroutines()`** → すべてのコルーチンを停止

## 4. コルーチンの応用

### 条件を満たすまで待つ
コルーチンは `while` ループと `yield return` を組み合わせることで、特定の条件を満たすまで待機できます。

```csharp
IEnumerator WaitUntilExample()
{
    Debug.Log("キー入力待ち...");
    yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
    Debug.Log("スペースキーが押された！");
}
```

### 徐々に値を変化させる（Lerpを使った移動）

```csharp
IEnumerator MoveOverTime(Transform obj, Vector3 target, float duration)
{
    float elapsed = 0;
    Vector3 start = obj.position;
    while (elapsed < duration)
    {
        elapsed += Time.deltaTime;
        obj.position = Vector3.Lerp(start, target, elapsed / duration);
        yield return null;
    }
    obj.position = target;
}
```

## 5. コルーチンの注意点

### ① `Update()` よりもコルーチンが適切な場合
- **時間経過を伴う処理（例：一定時間待機、アニメーション）**
- **徐々に変化する処理（例：フェード、移動）**

### ② `yield return` を使わないと無限ループ
以下のように `yield return` を書かないと、**無限ループ** になってしまうので注意！

```csharp
IEnumerator InfiniteLoop()
{
    while (true)
    {
        Debug.Log("無限ループ");
        yield return null; // これを忘れるとフリーズする
    }
}
```

### ③ `StartCoroutine()` の戻り値を管理する
- `Coroutine` 型の変数に保存すれば、後から `StopCoroutine()` で制御できる。

---

## まとめ
| 項目 | 説明 |
|------|------|
| **コルーチンとは？** | 時間経過を伴う処理をフレームをまたいで実行する仕組み |
| **定義方法** | `IEnumerator` を返すメソッドとして作成し、`yield return` を使う |
| **開始方法** | `StartCoroutine(コルーチン名())` |
| **停止方法** | `StopCoroutine()` or `StopAllCoroutines()` |
| **代表的な `yield return`** | `null` (次のフレーム), `WaitForSeconds()`, `WaitUntil()` など |
| **活用例** | 一定時間待機、移動アニメーション、キー入力待ち |

コルーチンを使いこなせば、時間経過を伴う処理をスムーズに実装できます！