今回やること
- 壁オブジェクトの作成
- 迷路生成プログラムの作成
1.壁オブジェクトの作成
この講座も残すところ後1~2回くらいとなりました。
本講座で作るゲームはいわゆる「迷路ゲーム」なのですが、迷路の作成に使うのは実装が簡単な「棒倒し法」というアルゴリズムです。
このアルゴリズムは、ざっくり言うと「1マスおきに格子状に置いた棒を上下左右ランダムに倒すといい感じに迷路ができる」というものです。
このアルゴリズムを使って迷路を作るうえで、プログラムで必要になるのは以下の処理です。
- 棒となるオブジェクトを上下もしくは左右に拡大する
- 棒となるオブジェクトの位置を調整する
- 棒となるオブジェクトを格子状に配置する
では、順番にやっていきましょう。
まずは、棒となるオブジェクト用のプログラムを作ります。
新しくプログラムファイルを作成して(この講座ではWall.cs)、以下のように記述してください。
using UnityEngine;
public class Wall : MonoBehaviour
{
void Start()
{
int num = Random.Range(0, 4);
if(num == 0)
{
}
else if(num == 1)
{
}
else if (num == 2)
{
}
else
{
}
}
}
ここで使われているRandom.Range(a,b)という関数は、Unityが実装している独自の関数です。a~(b-1)までのランダムな整数を与えます。
つまり、これで変数numは0~3までのランダムな値となるので、それに応じてifで処理内容を変えて上下左右のランダムな拡大処理を行うわけです。
では、それぞれのif文に以下のように書いてください。それぞれ似たような内容なので一つ書いたらコピペの方が断然いいです。
using UnityEngine;
public class Wall : MonoBehaviour
{
void Start()
{
int num = Random.Range(0, 4);
if(num == 0)
{
transform.localScale = new Vector3(1, 2, 1);
transform.Translate(0, 0.5f, 0);
}
else if(num == 1)
{
transform.localScale = new Vector3(1, 2, 1);
transform.Translate(0, -0.5f, 0);
}
else if (num == 2)
{
transform.localScale = new Vector3(2, 1, 1);
transform.Translate(0.5f, 0, 0);
}
else
{
transform.localScale = new Vector3(2, 1, 1);
transform.Translate(-0.5f, 0, 0);
}
}
}
ここで出てくるtransform.localscaleというのはインスペクタでいう以下の部分です。これは、元の大きさと比べた拡大率を3次元ベクトル(Vector3)で表しています。上下どちらかに倒すならy軸に拡大して、左右どちらかならx軸に拡大すればいいわけです。ここで使っているnew (型名)(~) という書き方はVector3などその変数自体が他に変数を内包しているようなものを新しく作るときに使います。
transform.position, .rotation, .localScaleでオブジェクトの位置、向き、大きさにそれぞれアクセス可能です。
これはインスペクタのtransformとも対応しています。
下のTranslateは、オブジェクトの位置を()内のベクトル分位置をずらすというものです。xy軸それぞれに拡大しても左右に少しずつ拡大するだけなので、この処理で0.5だけ上下左右にずらしているわけです。
それでは、前回の講座と同様にBoxCollider2Dを持ったSquareを作成して、作ったプログラムを追加してください。
比較のために完成したオブジェクトをいくつかコピーしてテストプレイすると...
このように、ランダムに上下左右に伸びることが確認できました。
このオブジェクトは後で量産して使うので、プレハブ化しておいてください。
2.迷路生成プログラムの作成
棒となるオブジェクトが完成したので、次はこれを配置するプログラムを作成します。
ふたたび新しくプログラムを作成して(本講座ではMazeCreator.cs)、以下のように書いてください。
using UnityEngine;
public class MazeCreator : MonoBehaviour
{
public GameObject wallObj;
void Start()
{
for(int y = 0;y < 4; y++)
{
for(int x = 0;x < 4; x++)
{
}
}
}
}
ここでは,二重にfor文を使うことで格子状にオブジェクトを配置する処理を実装します。変数yが0,1,2,3と変わるたびにxを0,1,2,3と増やす二重のループ処理を行うので、格子それぞれに対する処理が可能なわけです。
では、ここに以下のように書いてください。
using UnityEngine;
public class MazeCreator : MonoBehaviour
{
public GameObject wallObj;
void Start()
{
for(int y = 0;y < 4; y++)
{
for(int x = 0;x < 4; x++)
{
GameObject obj = Instantiate(wallObj);
wallObj.transform.position = new Vector3(x * 2 + 1, y * 2 + 1, 0);
}
}
}
}
この処理では、x,yに応じた位置にオブジェクトをInstantiateで生成して配置しています。今回はオブジェクトを以下のように配置したいので、x * 2+1,y * 2+1という値をtransform.positionに代入しています。
では、空のオブジェクトを作成して、作ったプログラムを追加した後、wallObjに棒のプレハブファイルを追加して...
テストプレイを押すと、棒が格子状に配置されていますが、画面からはみ出ています。
これは、ゲームの描画範囲を司るシーン内のカメラオブジェクトの範囲外に棒が配置されているからです。Cameraのxy位置を棒の配置範囲の中心(4,4)に移動させた後、描画範囲を6に拡大させましょう。sizeは上下のカメラの描画範囲を表します。
この状態でテストプレイすると...
マップ全体が表示されました。
外枠も作っておきましょう。前と同じようにBoxCollider2Dを持った壁となるオブジェクトをコピペで4つ作成して...
迷路の範囲に合わせて以下のようにサイズ・位置を設定しましょう。
| 番号 | Position | Scale |
|---|---|---|
| 壁1 | (-1, 4, 0) | (1, 11, 1) |
| 壁2 | (4, -1, 0) | (11, 1, 1) |
| 壁3 | (9, 4, 0) | (1, 11, 1) |
| 壁4 | (4, 9, 0) | (11, 1, 1) |
ついでに、プレイヤーの大きさも少し小さくしておきましょう。格子の大きさと完全に一緒だと動かしづらいです。
最後に、プレイヤーの位置を(0,0,0)に直しておいて...
これで迷路ゲームの原型が作成しました。テストプレイするといい感じに迷路が生成されてます。
次回は迷路のゴールを作成して、仕上げを行います。お疲れさまでした~
