Unity(C#)でよく使うコレクション型「LIST型」を4つ厳選して解説します。単なる配列(Array)より便利な使い方ができて、おなかまわり(コード)がすっきりします!
その前に、基本のはなし。
C# における基本的な配列型 Array
は、ひとつのインデックスに対してひとつのデータを保持する構造です。
ほとんどのプログラミング言語に存在する、いわば「おなじみのやつ」ですね。
ただし、存在しないインデックスにアクセスしようとするとエラー(IndexOutOfRangeException)が発生する点には注意が必要です。
GameObject[] prefabArray = new GameObject[3];
この例では、prefabArray
に 3 つの GameObject
を格納するスペースが確保されています。インデックスは 0
~ 2
までの3個が使用できます。この場合、インデックス 3~ にアクセスしようとするとエラーになります。
以上を踏まえ、他の型を見てみましょう。
List<T>
- 可変長の配列(Array と似ているが、配列の長さを確保する必要がない)
- 要素の追加は
list.Add
- 要素数の取得は
list.Count
var list = new List<GameObject>();
list.Add(prefab1); //追加
Debug.Log(list.Count); //要素数(出力=1)
Queue<T>
- FIFO(先入れ先出し) の操作構造。
- キューと読む。(キュエウエではない)
- 要素の追加は
queue.Enqueue
- 最初に追加した要素を取得して削除は
queue.Dequeue
- 削除せずに取得のみは
queue.Peek
- 要素の全削除は
queue.Clear
- 要素数の取得は
queue.Count
- 指定した要素があるかチェックするには
queue.Contains
- あれば true, なければ false を返す
var queue = new Queue<GameObject>();
queue.Enqueue(prefab1); //1番目に追加
queue.Enqueue(prefab2); //2番目に追加
var prefab = queue.Dequeue(); //1番目の要素を取得して削除
Stack<T>
- LIFO(後入れ先出し) の操作構造。
- 要素の追加は
stack.Push
- 最後の追加した要素を取得して削除は
stack.Pop
- Queueと同様にPeek, Clear, Count, Contains を使用可能
Stack<GameObject> stack = new Stack<GameObject>();
stack.Push(prefab1); //1番目に追加
stack.Push(prefab2); //2番目に追加
GameObject prefab = stack.Pop(); //2番目の要素を取得して削除
Dictionary<TKey, TValue>
- キーと値のペア を管理。
- 値にList型を指定して入れ子にすることもできる。
- 要素の追加は
dictionary.Add
- 指定したキーを持つ要素の削除は
dictionary.Remove
- 成功なら true, 失敗なら false を返す
- 指定したキーに関連付けられた要素の取得は
dictionary.TryGetValue
- 成功なら true, 失敗なら false を返す
- 値の存在チェックと取得を同時に行える神メソッド
- 指定したキーがあるかチェックするには
dictionary.ContainsKey
- 他にも機能がめっちゃある(公式リファレンス参照)
var dict = new Dictionary<string, int>();
dict["apple"] = 3;
if (dict.TryGetValue("apple", out var count)) {
Debug.Log(count); // 3
}
全件を取得するにはforeachがおすすめ。
foreach (Dictionary<string, GameObject> dict in dictionary)
{
var key = dict.Key; // string
var val = dict.Value; // GameObject
}
「2次元List」の実装方法
C#で多次元リストを宣言するための組み込みメソッドは用意されていないようなので、自前でコードを組むことになります。ポイントは赤字ハイライトの部分です。
List<List<int>> Data = new List<List<int>>();
for (int i=0; i<3; i++)
{
List<int> Nums = new List<int>();
Nums.Add(i);
Nums.Add(i+1);
Nums.Add(i+2);
Data.Add(Nums);
}
この場合、Dataリストの中身はこのようになります。
Nums[0] | Nums[1] | Nums[2] | |
Data[0][n] | 0 | 1 | 2 |
Data[1][n] | 1 | 2 | 3 |
Data[2][n] | 2 | 3 | 4 |
Data[2]のNums[2]にアクセスしたい場合はこうします。
Debug.Log(Data[2][2]); //「4」と出力される
単一の型の代わりにClassを代入すれば、複数の型を一気にぶっこめます。
public class Chara
{
public Long Id { get; set; } //キャラID
public string Name { get; set; } //名前
public int HP { get; set; } //ヒットポイント
public bool isDead { get; set; } //死亡フラグ
}
List<Chara> PTMember = new List<Chara>();
for (int i=0; i<3; i++)
{
Chara _chara = new Chara();
_chara.Id = i;
_chara.Name = $"どんぐり{i}";
_chara.HP = 20 + i;
_chara.isDead = false;
PTMember.Add(_chara);
}
この場合、PTMemberリストの中身はこのようになります。
Id | Name | HP | isDead | |
PTMember[0] | 0 | どんぐり0 | 20 | false |
PTMember[1] | 1 | どんぐり1 | 21 | false |
PTMember[2] | 2 | どんぐり2 | 22 | false |
PTMember[2]のHPにアクセスしたい場合はこうします。
Debug.Log(PTMember[2].HP); //「22」と出力される
本記事は旧ブログで投稿した同テーマのエントリーを大幅に加筆修正したものです。