とあるプログラマの備忘録

都内某所に住むプログラマが自分用に備忘録を残すという趣旨のブログです。はてなダイアリーから移動しました!

【Unity 入門】ダンジョンゲーを作ってみたい 第一回「ダンジョン作ってみる」

私達アラサーとしてはやっぱりダンジョンという言葉に胸躍らされてしまいます。
ってことでトルネコウィザードリーの中間位の3Dダンジョンゲーを作ってみたいなと思います。

1.床となるフロアを作りたい
1-1.床を作る
何にせよ床が無いと始まらないので床を作ります。

Hierarcy > Create > Plain
で床を作ります。

名前をfloorとかにしておきましょう。

positionのyが-0.5になっているは1のスケールの壁を作ると半分が地下に埋まってしまうので床を少し下に下げているという事です。
これを0で作りたい場合は壁のy軸を+0.5してやると良いと思います。

1-2.床にテクスチャ貼る
Assets > Create > Materialで床にテクスチャ貼ります。
今回は「WebTreats_NaturalGrunge3」のテクスチャを貼りたいと思います
(もしかしてこのテクスチャUnity入門の本について来たテクスチャダッタかも知れないので無い場合は適当に床っぽい奴を貼ってください)
このマテリアルをHierarchyのさっき作った床オブジェクトにドラッグ&ドロップしておきましょう。

こんな床が出来上がりました

1-3.一応これをプレハブ化
今のところ使ってないですけどこれを一応プレハブ化しておきましょう。
Assets > Create > Prefabで空のプレハブを作って
Hierarchy > floorをドラッグ&ドロップしておきます。プレハブ化して置けば例えばマップサイズを変更したときなどにサイズを可変にできるので
便利です。

2.周りに壁を作る
プレイヤーが落ちてしまわない様に、周りは全て壁で埋めてあげたいと思います。
一個ずつオブジェクトを置いていては日が暮れるので、スクリプトで周りの壁を生成したいと思います。

2-1.とりあえず周りの壁の元になるプレハブを作る
スケールが1の壁プレハブを作成します(プレハブの作り方は何度もやっているので割愛)
こんなプレハブを作ります。名前は「DWall」とでもしておきます。

2-2.周りの壁を作るスクリプトを書く
今まではjsで書いていたんですが、どうやらUnityの主流となる言語の第一党はC#の様なのでこれからはC#で書いて行こうと思います。

using UnityEngine;
using System.Collections;

public class MapGenerator : MonoBehaviour {

	public GameObject wallPrefab;
	private int default_x_max = 19;
	private int default_z_max = 19;

	// Use this for initialization
	void Start () {
		//枠を作るメソッド呼び出し
		CreateMapWaku();
	}
	
	//枠を作るメソッド
	void CreateMapWaku()
	{
     //ループしながらz軸の上と下2列に枠を作ります
		for(int dx = 0; dx <= default_x_max; dx++){
			Instantiate(defaultWallPrefab, new Vector3(dx, 0, 0), Quaternion.identity);
			Instantiate(defaultWallPrefab, new Vector3(dx, 0, default_z_max), Quaternion.identity);
		}
		
     //同じくx軸に右と左に枠を作ります
		for(int dz = 0; dz <= default_z_max; dz++){
			Instantiate(defaultWallPrefab, new Vector3(0, 0, dz), Quaternion.identity);
			Instantiate(defaultWallPrefab, new Vector3(default_x_max, 0, dz), Quaternion.identity);
		}
		
	}

このスクリプトはMapGeneratorと名付けます

2-3.Hierarchyに適応
メニュー > GameObject > Create EmptyでHierarchyに空のゲームオブジェクトを作ります。
名前は「mapGenerator」とかにしておきましょう
さっき作ったスクリプトをこれにドラッグ&ドロップします。

InspectorのDefaultWallPrefabにさっきプレハブかしておいたDWallをセットします
(※まだWallPrefabはまだ出てきてないと思います。)

さて実行してみましょう
こんな感じで枠の壁ができあがりましたでしょうか?できたら成功です。

3.マップの中身を作る
3-1.中身のマップ用のプレハブを作る
名前は「Wall」としておきましょう

3-2.マップ生成スクリプトを書く
中身のマップを生成するスクリプトを作りたいとおもいます。
とは行ってもさっき作ったマップジェネレーターにマップ用のメソッドを追加するだけですしおすし。

using UnityEngine;
using System.Collections;

public class MapGenerator : MonoBehaviour {

    //こっちは中身のマップ用のプレハブ
	public GameObject wallPrefab;
    //こっちは枠様のプレハブ
	public GameObject defaultWallPrefab;
	private int default_x_max = 19;
	private int default_z_max = 19;

	// Use this for initialization
	void Start () {
		//これがマップの元になるデータ
		string map_matrix  = "022520000000000000:022220000000000000:022250000000000000:025251111111111110:022220000000000010:000100000000000010:000110000000000010:000010022500000010:000010032200000010:000010052200000010:000011152200000010:000000022200000010:000000000000000010:000000000000002522:000000000000015222:000000000000002222:000000000000000000:000000000000000000";
		
		//wakucreate
		CreateMapWaku();
		
		// 引数にこれを入れてマップ生成する
		CreateMap(map_matrix);
	}
	
	//CreateWaku
	void CreateMapWaku()
	{
		for(int dx = 0; dx <= default_x_max; dx++){
			Instantiate(defaultWallPrefab, new Vector3(dx, 0, 0), Quaternion.identity);
			Instantiate(defaultWallPrefab, new Vector3(dx, 0, default_z_max), Quaternion.identity);
		}
		
		for(int dz = 0; dz <= default_z_max; dz++){
			Instantiate(defaultWallPrefab, new Vector3(0, 0, dz), Quaternion.identity);
			Instantiate(defaultWallPrefab, new Vector3(default_x_max, 0, dz), Quaternion.identity);
		}
	}
	
	//マップを作るメソッド
	void CreateMap(string map_matrix)
	{
                //「:」をデリミタとして、mapp_matrix_arrに配列として分割していれます
		string[] map_matrix_arr = map_matrix.Split(':');

     //map_matrix_arrの配列の数を最大値としてループ
		for(int x = 0; x < map_matrix_arr.Length; x++){
        //xを元に配列の要素を取り出す
			string x_map = map_matrix_arr[x];
        //1配列に格納されている文字の数でx軸をループ
			for(int z = 0; z < x_map.Length; z++){
                                //配列から取り出した1要素には022520000000000000こんな値が入っているのでこれを1文字づつ取り出す
				int obj = int.Parse(x_map.Substring(z, 1));
				
                                //もしも0だったら壁ということで壁のプレハブをインスタンス化してループして出したx座標z座標を指定して設置
				if(obj == 0){
					Instantiate(wallPrefab, new Vector3(x + 1, 0, z  + 1), Quaternion.identity);
				}
			}
		}
		
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

こんなかんじでしょうか、このスクリプトは既にHierarchyのマップジェネレーターに組み込まれているので、
さっきなかったwallPrefabのセットだけで動く筈です。

さっき無かったWall Prefabをさっき作ったプレハブをセットします。

さてそれではシュミレートしてみましょう。
おおーダンジョンっぽいマップができました!

ちなみにマップの右上の通路が途中で途切れているのはマップテキストがちょっと不完全だっただからです、
通路をつくってもよし、部屋をつくってもよしでマップテキストを適当に変更してみましょう。

今回は0は壁というものだけでしたが、マップテキストを見ると0の他に2,3,5などあると思います。
これは後々階段とかモンスターとかアイテムなんかを配置する為にこうなっているだけです。

そんなこんなで今回はここまでです。
次回はキャラクターを置いて、ダンジョン内をうろうろさせたいと思います。

関連記事
【Unity 入門】ダンジョンゲーを作ってみたい 第一回「ダンジョン作ってみる」
【Unity 入門】ダンジョンゲーを作ってみたい 第二回「キャラクターをダンジョン内で動かす」