【Unity】Unity開発者のためのC#配列・List入門 - 複数のデータをまとめて扱う

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

enemy1, enemy2, enemy3...と変数を増やしていませんか?複数のデータをまとめて扱う「配列」と「List」の使い方を、Unityでの実用例(スポーン地点の管理・敵リスト)とともに初心者向けに解説します。

敵を3体出したいから enemy1, enemy2, enemy3 と変数を3つ作った——動きはしますが、10体になったら変数10個、処理も10回コピペすることになります。この「同じ種類のデータがたくさんある」問題を一気に解決するのが、C#の コレクション、その代表である 配列List です。

この記事では、配列とListの基本、決定的な違いと使い分け、そしてUnityならではの実用例(Inspectorでのスポーン地点管理・敵リストの管理)までを解説します。

配列のイメージ。番号付きの棚にブロックが順番に並んでいる

この記事でわかること

  • 変数を番号付きでまとめて扱う「配列」の宣言・アクセス・ループ
  • 伸び縮みする「List」の使い方(Add / Remove / Count)
  • 配列とListの使い分け基準
  • Inspector連携や敵リスト管理など、Unityでの実用パターン

Sponsored

配列:番号付きの箱をまとめて作る

配列(array) は、同じ型の変数を「番号付きの棚」としてまとめて確保する仕組みです。まずイメージを掴んでください。

配列の概念図。int型の箱が0番から4番まで1列に連結された棚になっていて、番号(添字)で各箱にアクセスできる

棚の1マス1マスが変数で、それぞれに 添字(インデックス) という番号が付いています。重要なのは、番号が0から始まることです。5個の配列なら、番号は0〜4になります。

using UnityEngine;

public class ArrayExample : MonoBehaviour
{
    void Start()
    {
        // 要素数5のint配列を作る(全要素は0で初期化される)
        int[] scores = new int[5];

        // 添字を指定して読み書きする(0始まり!)
        scores[0] = 100;
        scores[1] = 85;

        // 最初から中身を決めて作ることもできる
        string[] stageNames = { "Forest", "Cave", "Castle" };

        // Lengthで要素数を取得
        Debug.Log($"ステージ数: {stageNames.Length}"); // 3

        // foreachで全要素を順番に処理
        foreach (string name in stageNames)
        {
            Debug.Log($"ステージ: {name}");
        }
    }
}

注意: 存在しない番号にアクセスすると IndexOutOfRangeException というエラーになります。要素数5の配列に scores[5] と書くのが定番の間違いです(最後の要素は scores[4])。

配列は 作った時点で要素数が固定 されます。「あとで1個増やしたい」はできません。そこで登場するのがListです。

List:伸び縮みするリスト

List は、要素を後から自由に追加・削除できる「伸び縮みする棚」です。使うにはファイル先頭に using System.Collections.Generic; が必要です。

配列とListの比較図。配列はマス目が固定された棚で作った後は増やせないが、Listは要素を追加すると棚が自動で伸びる

List<int> のように、<> の中に入れたい型を書きます(この記法は GetComponentの記事 で登場したジェネリックと同じ仕組みです)。

using System.Collections.Generic; // Listに必要!
using UnityEngine;

public class ListExample : MonoBehaviour
{
    void Start()
    {
        // 空のListを作る
        List<string> inventory = new List<string>();

        // Add: 末尾に追加(棚が自動で伸びる)
        inventory.Add("回復薬");
        inventory.Add("鉄の剣");
        inventory.Add("盾");

        // Countで現在の要素数を取得(配列のLengthに相当)
        Debug.Log($"アイテム数: {inventory.Count}"); // 3

        // 添字アクセスは配列と同じ
        Debug.Log($"最初のアイテム: {inventory[0]}"); // 回復薬

        // Remove: 指定した要素を削除(棚が縮む)
        // ※同じ要素が複数あっても、削除されるのは「最初に一致した1件」だけ
        inventory.Remove("回復薬");

        // Contains: 持っているかチェック
        if (inventory.Contains("鉄の剣"))
        {
            Debug.Log("剣を装備できます");
        }
    }
}
Sponsored

配列とListの使い分け

特徴配列 (int[])List (List<int>)
要素数作成時に固定自由に増減できる
要素数の取得.Length.Count
追加・削除できないAdd / Remove
向いている用途個数が決まっているデータゲーム中に増減するデータ

判断基準はシンプルです。

  • 個数が最初から決まっている(ステージ一覧、スポーン地点、装備スロット)→ 配列
  • ゲーム中に増えたり減ったりする(出現中の敵、インベントリ、獲得済み実績)→ List

迷ったらListで始めて構いません。配列が本領を発揮するのは「個数固定」という制約が設計の意図を伝える場面や、パフォーマンスを詰める場面です。

Unityでの実用例

実用例1: Inspectorでスポーン地点を管理する

public な配列は Inspectorに一覧として表示され、ドラッグ&ドロップで設定できます。これがUnityでコレクションが最初に活躍する場面です。

Inspectorでの配列設定の図。Spawn Pointsという配列スロットに、シーン内の3つのスポーン地点オブジェクトをドラッグして割り当てている
using UnityEngine;

public class EnemySpawner : MonoBehaviour
{
    public GameObject enemyPrefab;

    // Inspectorに「Spawn Points」として一覧表示される
    public Transform[] spawnPoints;

    void Start()
    {
        // すべてのスポーン地点に敵を1体ずつ生成
        foreach (Transform point in spawnPoints)
        {
            Instantiate(enemyPrefab, point.position, point.rotation);
        }
    }
}

シーンに空のGameObjectを3つ置いて、Inspectorの Spawn Points にドラッグするだけ。地点を増やしたくなったら、コードを触らずInspectorで要素を足せます。

実用例2: 出現中の敵をListで管理する

「今シーンにいる敵」は倒されて減り、スポーンで増える——まさにList向きのデータです。

敵のList管理の実例図。activeEnemiesリストに、スポーンした敵がAddで加わり、撃破された敵がRemoveで抜けていく。Countが0になったらウェーブクリア
using System.Collections.Generic;
using UnityEngine;

public class EnemyManager : MonoBehaviour
{
    // 出現中の敵を管理するリスト
    private List<GameObject> activeEnemies = new List<GameObject>();

    public void RegisterEnemy(GameObject enemy)
    {
        activeEnemies.Add(enemy); // スポーン時に追加
    }

    public void UnregisterEnemy(GameObject enemy)
    {
        activeEnemies.Remove(enemy); // 撃破時に削除

        // 全滅チェックもCountを見るだけ
        if (activeEnemies.Count == 0)
        {
            Debug.Log("ウェーブクリア!");
        }
    }
}

注意: foreach でListを回している最中Remove すると InvalidOperationException が発生します。ループ中に削除したい場合は、for 文で末尾から前へfor (int i = list.Count - 1; i >= 0; i--))回すのが定番の回避策です。

Sponsored

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

配列とListに慣れたら、次はこのあたりが視野に入ってきます。

  • 「名前で引く」ならDictionary: Dictionary<string, int> を使うと、items["回復薬"] のように番号ではなくキーで値を引けます。アイテムIDとデータの対応表などで大活躍します。
  • プレハブの量産管理と相性抜群: Listで管理した敵やアイテムを効率よく生成・破棄する次のステップが オブジェクトプーリング です。オブジェクトプーリングの記事 で「Listを使った再利用の仕組み」として登場します。
  • 大量データの増減はGCに注意: Listの要素追加は内部で配列の作り直しが起きることがあり、大量に繰り返すとGC(ガベージコレクション)の負荷になります。気になり始めたら GCの記事 が参考になります。
  • Listをpublicでそのまま公開しない設計もある: public List<...>にすると、他のどのスクリプトからも勝手にAdd/Removeできてしまいます。慣れてきたら、Listはprivateにして「追加・削除の窓口メソッド」だけを公開する形(先ほどのRegisterEnemy/UnregisterEnemyがまさにこれ)にすると、バグの入り口をぐっと減らせます。

まとめ

複数のデータをまとめて扱うコレクションは、ゲームロジックの土台です。

  • 配列は「番号付きの固定棚」。宣言時に要素数が決まり、.Length と添字(0始まり)で扱う。
  • Listは「伸び縮みする棚」。Add / Remove / .Count で自由に増減できる。using System.Collections.Generic; を忘れずに。
  • 使い分けは「個数が決まっているなら配列、増減するならList」。迷ったらListでOK。
  • publicな配列・ListはInspectorに一覧表示され、ドラッグ&ドロップで設定できる。
  • foreach中のRemoveは例外になる。ループ中の削除はforで末尾から。

enemy1, enemy2, enemy3 とはもうお別れです。10体でも100体でも、コレクションなら同じ数行のコードで扱えます。