参考:http://wiki.unity3d.com/index.php?title=Which_Kind_Of_Array_Or_Collection_Should_I_Use%3F
Unityの広義の配列―コレクション―はいくつか種類がある。それぞれ宣言や代入、値の取出しの記述が異なる。また、自由度が高い反面、使わないほうがよいものもある。
1)ビルトイン配列(Built-in Array)
もっとも基本的な配列で、もっとも高速。ただし宣言時に要素数を指定する必要がある。が、宣言後にリサイズは可能。(System.Array.Resize(ref myArray, size))で行う。)
C#での宣言、代入、リサイズは次のように行う。ただし、多次元のビルトイン配列はリサイズできない。
TheType myArray = new TheType[lengthOfArray]; // declaration int[] myNumbers = new int[10]; // declaration example using ints GameObject[] enemies = new GameObject[16]; // declaration example using GameObjects int howBig = myArray.Length; // get the length of the array myArray[i] = newValue; // set a value at position i TheType thisValue = myArray[i]; // get a value from position i System.Array.Resize(ref myArray, size); //resize array string[] weapons = new string[] { "Sword", "Knife", "Gun" }; float[] alphas = new float[] { 1.0f };
2)Javascript配列(Javascript Array)
標準的な.netクラスにはない、Unity独自の配列。ただし名前通り、javascript型スクリプトでのみつかえ、C#型では使えない。
このため、サイズ変更可能、要素の型を宣言する必要がないなど柔軟性が高いが、反面、性能的にはもっとも遅い。
Javascript Arrayは基本的にはArrayListにラッパーをかけたものとみなせ、同様のことはObjectリストで実現できる。しかも速い。Javascript Arrayは「過去の遺産」と考えた方がよさそう。
3)アレイリスト(ArrayList)
Javascript Array以上に柔軟性がある(たとえば要素数を変更できるなど)が、性能上は遅い(*)。またArrayList自体には型はなく、任意の型を要素として持つことができる。型の混在も可能。
ただし、Generic Listの登場によりArrayListの存在意義はなくなったといわれる。旧式のコードとの互換性上のものと考えた方がよさそう。
(*)性能面のハンデの多くは宣言時に要素数を宣言しないため、という報告もある。つまり、ArrayListでも要素数を固定すれば、速度は改善するらしい。
ArrayList myArrayList = new ArrayList(); // declaration myArrayList.Add(anItem); // add an item to the end of the array myArrayList[i] = newValue; // change the value stored at position i TheType thisItem = (TheType) myArray[i]; // retrieve an item from position i myArray.RemoveAt(i); // remove an item from position i var howBig = myArray.Count; // get the number of items in the ArrayList
4)ハッシュテーブル(Hashtable)
'key-value'方式で要素を参照する配列。
key, valueともにどんな型でもよい(untype)。型の混在も可能。(keyは通常はString型であることがおおいが。)このため、Hashtableから要素を取り出す際は、ユーザがCastしてやる必要がある。
ただし、ArrayListよりもGeneric Listが良いのと同じように、近年は、HashtableよりDictionaryを使う方が良い。
Hashtable myHashtable = new Hashtable(); // declaration myHashtable[anyKey] = newValue; // insert or change the value for the given key ValueType thisValue = (ValueType)myHashtable[theKey]; // retrieve a value for the given key int howBig = myHashtable.Count; // get the number of items in the Hashtable myHashtable.Remove(theKey); // remove the key & value pair from the Hashtable, for the given key.
5) ジェネリック・リスト(Generic List)
Generic Listは、List
- 要素の値を取出す際、型キャストが不要。
- ArrayListより速い
という利点がある。
つまり、特定の型のみ扱うことがわかっている場合は、ArrayListよりGeneric Listを使う方が良い。
using System.Collections.Generic; List<Type> myList = new List<Type>(); // declaration List<int> someNumbers = new List<int>(); // a real-world example of declaring a List of 'ints' List<GameObject> enemies = new List<GameObject>(); // a real-world example of declaring a List of 'GameObjects' myList.Add(theItem); // add an item to the end of the List myList[i] = newItem; // change the value in the List at position i Type thisItem = List[i]; // retrieve the item at position i myList.RemoveAt(i); // remove the item from position i
6) ジェネリック・ディクショナリー(Generic Dictionary)
HashtableのGneric List版。宣言時にkey, valueの型を指定する。このため、Gneric Listと同じ利点が得られる。
using System.Collections.Generic; // declaration: Dictionary<KeyType,ValueType> myDictionary = new Dictionary<KeyType,ValueType>(); // and a real-world declaration example (where 'Person' is a custom class): Dictionary<string,Person> myContacts = new Dictionary<string,Person>(); myDictionary[anyKey] = newValue; // insert or change the value for the given key ValueType thisValue = myDictionary[theKey]; // retrieve a value for the given key int howBig = myDictionary.Count; // get the number of items in the Hashtable myDictionary.Remove(theKey); // remove the key & value pair from the Hashtable, for the given key.
7) 2次元配列(2D Array)
以上はすべて1次元の配列について述べてきた。Unityでは2次元以上の配列を使うこともできる。以下は2次元配列についてのべるが、3次元、4次元…といった多次元配列を扱うこともできる。
「一般の」2次元配列の宣言では、外側・内側の2要素の要素数を指定する。
// declaration: string[,] myArray = new string[16,4]; // a 16 x 4 array of strings // and a real-world declaration example (where 'Tile' is a user-created custom class): Tile[,] map = new Tile[32,32]; // create an array to hold a map of 32x32 tiles myArray[x,y] = newValue; // set the value at a given location in the array ValueType thisValue = myArray[x,y]; // retrieve a value from a given location in the array int width = myArray.GetLength(0); // get the length of 1st dimension of the array int length = myArray.GetLength(1); // get the length of 2nd dimension of the array
一方「ジャグ(jagged)」2次元配列では、(内側の)要素の数がそろっていなくても良い。
var myJaggedArray = [ [1, 2, 3], [4, 5], [6, 7, 8, 9, 10] ]; // a jagged int array myArray[x][y] = newValue; ValueType thisValue = myArray[x][y];
ちなみに、「ビルトイン配列(たとえば、GameObject[])を要素にもつジェネリック・リスト」を作るには次のように書く。
GameObject[] go1;
GameObject[] go2;
GameObject[] go3;
List<GameObject[]> gos = new List<GameObject[]>{go1,go2,go3};
以上、Unityで扱われる広義の配列について述べた。利用指針は次のようになるだろう。
・大きさがわかっているケースは、ビルトイン配列を使う。メモリ効率も速度ももっともよい。
・ArrayListのかわりにGneric Listを、Hashtableの代わりにGeneric Dictionaryを使う。
・Javascript Arrayは使わない。
要するに、型のキャストを避けるべき。
開発時はArrayListやHashtableを使ってもよいが、リリース時はGnericに変換するとよいだろう。