Unity で テトリス風ゲームを作ってみる#5
前回の続き
今回は、テトリミノを上から落としてフィールドに着地させる処理を考える。
テトリミノの生成
まずは、フィールド上部にテトリミノを生成する。再生されるテトリミノはランダムに決定したいので、Unity のRandom 関数を使って実現する。
Random 関数の初期化方法は、リファレンスに記載があるとおり
- UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
でOK。"using System" を追加しておかないとDateTime クラスを使えないので注意。
使用方法は、Range メソッドを使って
- var type = UnityEngine.Random.Range(0, 10);
とする。この例だと、0 以上 10 未満のランダム整数値が取得できる。
これをテトリミノの種類にキャストして利用すれば、ランダムなテトリミノを生成可能となる。
テトリミノ(および、その構成要素のブロック)は、ゲームの進行に合わせて動的に生成する必要がある。Unity ではPrefab という仕組みがあり、GameObject をPrefab という雛型にしておくことで、スクリプトから動的に生成/削除することができる。
例えば、こんな感じ。
- var prefab = Resources.Load("Prefabs/Tetrimino") as GameObject;
- var copyObject = Instantiate(prefab, this.transform);
"Prefabs/Tetrimino" は、予め作っておいたテトリミノPrefab のResource フォルダ上のパスを表している。Resources, Prefabs というフォルダは自分で作成したもの。
Hierarchy 上で作成したGameObject を作ったフォルダにドラックアンドドロップすれば、Prefab の完成。Prefab は、青色のアイコンで表示される。
Resources クラスは、Assets フォルダ配下のResources フォルダにあるオブジェクトにアクセスするためのクラス。この例では、Load 関数を使ってPrefab を動的に読みだすのに使っている。読みだしたPrefab をGameObject にキャストして、Instatiate 関数を使ってインスタンス化すれば、GameObject の動的生成の完了。
テトリミノの生成場所は、テトリミノのサイズのMAX が高さ 4、幅 4 なので、フィールド上の(3, 16)の位置とする(あとで調整するかも)。
テトリミノの落下
テトリミノはフィールドに生成後、一定周期ごと(レベル毎に周期は短くなる)に落下する。フィールドに着地すると、その場にブロックとしてとどまる。
一定周期ごとに落下する動作を実現する方法はいくつかあるが、一般的にはGameObjectのUpdate / FixedUpdate コールバック関数にて経過時間の計測し、落下時刻が経過した場合は、テトリミノを一段下に移動するということで実現可能。
-
- GameObject と Monobehaviour とイベント関数
GameObject は、Unity ゲームエンジンが管理するすべてのオブジェクトの大本のオブジェクトであり、ゲームキャラクターはもちろんのこと、各UIパーツや、カメラ、ライトも含めすべてがGameObject から派生して出来てる。Unity ゲームエンジンはこれらのGameObject の管理、制御を行っている。例えば、質量をもったキャラクターのGameObject であれば、重力の影響を計算して落下させる演算を行ったり、物体同士の衝突を計算したり。
一方で、Unity は、GameObject をスクリプトからも制御できる仕組みを提供しており、そのインタフェース的な仕組みがMonobehaviour クラスである。GameObject にはMonobehaviour クラスから派生したクラスをアタッチすることができ、スクリプトからそのGameObject を制御することができる。
具体的には、GameObject に発生する各種イベントをフックできるイベント関数がMonobehaviour クラスに定義されており、それらをオーバーライドすることでイベント発生時の挙動を独自に制御することが可能である。
今回使ったUpdate 関数は、ゲーム中、毎フレームごとに呼び出されるイベント関数になっている。当然、この関数の中で、ちょー重い処理を実行すると、Unity エンジンのゲームサイクルがブロックされるので、フレーム落ちが発生することになる。
テトリミノ落下の例では、フレーム更新時に呼ばれるUpdate イベント関数をオーバーライドして、経過時刻を計算し、一定値以上になったらテトリミノの位置を一段下げるという処理をスクリプトにて実現している。
テトリミノの着地
テトリミノがフィールドの枠ブロック、又はフィールド上のブロックに接すると着地判定となるが、着地からブロック化するまでには少し時間的な猶予が与えられる。(Wikiによると、0.5s程度)。
ブロックに接したかどうかは、Raycast による判定で実現できることはわかったので、あとは着地後にブロック化するまでの猶予時間を実現できればよい。
これも実現方法は落下の時刻経過を計測する方法と同様にUpdate イベント関数の中で0.5s をカウントすればよさそう。
試しにプロト実装した結果はOK。下記の動画では、着地後にブロック化した状態がわかるようにあえて色を黒に変色させている。
今回はプロトなので、細かい挙動は目をつむったが、猶予時間中の左右移動でさらに下に落下する場合や、猶予期間中に下キーを押された時の挙動などを実装していく必要がある。
次の記事