まずはこちらをダウンロードして実行してみてください.
このシーンをダブルクリックで開くことができる.
2500個のキューブの色を,Sin,Cos,キューブの位置,時間によって変えることで模様を作り出すプロジェクトになっています.
CubeのMvの値で振れ幅が変わります.
パラメータの調整によってはこのようになったりもします.
(色のパラメータなどは削除しているので,いじりたかったらソースコードを変えてみてください.)
たくさんのキューブを管理する
2500個のキューブを管理するのに50×50の2重配列を使っています.
配列とは次のようなものです.
int a0 = 0, a1 = 1, a2 = 2, a3 = 10;
等のように,複数のデータを,
int[] a = {0, 1, 2, 3, 10};
のようにまとめて管理することができる.
値を取り出すときは,
b = a[0] // bには0が代入される
b = a[4] // bには10が代入される
2重配列は,
int[,] a = { {0, 1},
{2, 3},
{4, 5}}
のように,先の配列を2重にすることができます.
値を取り出すときは
b = a[0,0] // bには0が代入される
b = a[1,0] // bには2が代入される
b = a[2,2] // 2番目の要素数は2なので,インデックスは1までしかないのでエラーとなる
今回はオブジェクトを管理したいので,
9: public GameObject[,] cube;
int の部分がGameObjectになる.
しかしこれは宣言しただけでまだ実体はない.
使用するには初期化が必要となる.
なぜ宣言と同時に初期化しないのかというと,管理するキューブの数がわからないので,
(事前に決めておけばわかるが,後から変えたりしたい!)
最初は宣言のみで,初期化時に
18: cube = new GameObject[cubeNum, cubeNum];
として,キューブを入れる準備をする.
これは先の例でいうと次のようになる.
public int[,] a; // まだ実体はない
a = new int[aNum, aNum]; // aNum×aNumの数だけ確保
事前に大きい数字を入れておいてもいいが,メモリが無駄になってしまうので,
初期化に時間をとれる場合はこのようにする.
2重ループ
19: for (int i = 0; i < cubeNum; i++) { // iに0~50まで代入
2重にループを行っている.
cube[i, j]の部分を書き出すと,
cube[0,1]=
cube[0,2]=
...
と,i,jにそれぞれ0~cubeNum - 1の値が代入されたものがそれぞれ実行される.
38: cube [i, j].renderer.material.color = (new Color (c1, 1.0F, c2, 1.0F))
renderer.material.color() でオブジェクトのマテリアルの色を変えることができる.
マテリアルがアタッチされていない場合は,Inspectorビューから手動でつける.
Color(r, g, b, α)
それぞれの成分の値を0~1.0で指定する.αは透明度.
赤:Color(1, 0, 0, 1)
緑:Color(0, 1, 0, 1)
青:Color(0, 0, 1, 1)
灰色:Color(0.5f, 0.5f, 0.5f, 1)
ほしい色のパラメータを知りたいときはペイントソフトのカラーパレットを見たり,色についてwebで調べたりする.
0~255で表されているときは0~1.0にマッピングして使用する.
位置によって色を変える
キューブの位置は,22行目でInstantiateで生成したときに new Vector3 (i, j, 0.0F) で,i,とjの値によって決めている.
これを色にも適用する.
色を滑らかに変化させる
三角関数など一定の周期をもつ関数を使用する.
35: c1 = Mathf.Sin (Time.time * i); // 一つはSin
色を時間ごとに変化させる
上のように Time.time を引数に混ぜる.
その他時間によって変化するパラメータがあれば何でもよい.
では次に別のプロジェクトでゲームを作ってみます.
こちらからダウンロードして同様に実行してみてください.

キーボードで操作できます.一度通った場所や,フィールド外に行ってしまうとゲームオーバーです.
ではソースコードを見ていきます.
先ほどのプロジェクトと同様に,キューブを2500個配列で管理します.(パソコンが重くなる場合は減らしてください)
今回はキューブを通過したかどうかも記録したいので,新たにキューブの状態を管理する
8: int[,] cubeState
も追加します.初期化の方法は同じです.
プレーヤーを上下左右キーで方向転換
プレーヤーの位置は int[] pos に入っています. x, y なのでそのままint x, y としても良いです.
一度キーを押すと,次にキーが押されるまではずっとその方向に進みます.
現在の進行方向を記録する変数 nowDir を用意します.
0:上,1:右...
等のように割り当てて nowDir に保持します.
上を押したときに上に進んでほしいので,
if("上が押された") nowDir = 0;
if("右が押された") nowDir = 1;
のように,キーが押されたときに nowDir の値を変更します.
プレーヤーを進める
プレーヤーは nowDir の方向に進みます.
ですが,
if(nowDir == 0){
pos[0] += 0;
pos[1] += 1;
} else if(nowDir == 1){
pos[0] += 1;
pos[1] += 0;
}
のように,それぞれの状態の場合ごとに処理を記述するのは面倒です.
事前に進む方向が4方向だと分かっているので, dir に用意しておきます.(11行目)
プレーヤーを進める処理を見てみると,
73: pos[0] += dir[nowDir, 0];
74: pos[1] += dir[nowDir, 1];
と,2行で済んでいます.
nowDir が0のときに注目すると,
pos[0] += dir[nowDir=0, 0] = dir[0, 0] = 0
pos[1] += dir[nowDir=0, 1] = dir[0, 1] = 1
nowDir が1のときは,
pos[0] += dir[nowDir=1, 0] = dir[1, 0] = 1
pos[1] += dir[nowDir=1, 1] = dir[1, 1] = 0
と,ちゃんと nowDir の方向に進む処理になります.
このようにすることで,処理を一つにまとめることができます.
また,今回はx,yと2つのパラメータしかないので必要性を感じませんが,ここもfor文で一つにまとめることができますね.
Aキーを押すとゲームを最初からにできるようにしています.
53: if (Input.GetKeyDown(KeyCode.A)) // Aキーを押すとリセット.
54: initGameState(); // キューブを生成したくはない.ゲームに関するデータだけ初期化.
キューブを生成する初期化とゲームの初期化を分けて,Aが押されると実行されるようになっています.
解説は以上です.言語の文法も含めて気になる部分はメールなどで聞いてください.
余裕があれば敵も作ってみてください.


