読者です 読者をやめる 読者になる 読者になる

Unity / VRゲーム開発日記@長崎

Unityを使ったVRのゲーム開発をやってます。

時職人の作り方 (2)- オブジェクトの並べ方

時職人作り方2回目です。


今回はストップウォッチ部を解説予定でしたが、
メニュー部にまだネタがありそうだったので、
もう少しそちらを説明していきます。

構成

今回は、アイコンの並べ方のロジックについてです。

以前も軽く触れましたが、アイコンメニューは実行時に
自動生成し、戻るアイコンはEditor上で予め配置しています。


よって、実行前と実行後は以下の様な感じになります。

  • 実行前

f:id:icoc_dev:20141009092644j:plain

  • 実行後

f:id:icoc_dev:20141009092700j:plain


各ステージは、エリアという単位でくくられていて、
全7エリアの、12ステージでゲームが構成されています。

アイコンの数分ループ

アイコンの作り方としては、
エリア と ステージ のループで回して、
その中でアイコンのオブジェクトを生成していく形です。


ただし、画面表示の都合上、4ステージ毎に
アイコンの折り返しをしています。


そのため、ステージをさらに行と列のループに分けています。

const int ICON_COL_NUM = 4;
const int ICON_ROW_NUM = 3;


void IconLayout ()
{
	for (int areaNo =0; areaNo<_areaNum; areaNo++) {

		for (int y=0; y < ICON_ROW_NUM; y++) {
			for (int x=0; x < ICON_COL_NUM; x++) {
				CreateIcon (areaNo, x, y);
			}
		}
	}
}

areaNoのループがエリアのループ。
ステージが増えても良いように、ループ回数はメンバ変数としています。

その中で、y座標と x座標に関してループしています。
列と行は、変えるつもりはなかったのでconstです。

今回は_areaNumは7なので、
エリア(7) * 行(3) * 列(4) = 84
で全84ステージ分のアイコンをCreateIconで実体化させています。


個別アイコンの位置決め

先ほどのループで、どのアイコンを作るかというところまで
確定しているので、あとはそこから詳細な位置を導き出します。

略以降はアイコンの色変化とかをさせてますが、
アイコンパターンが幾つかあり煩雑なので、
次回の説明に回します。

以下、位置情報確定のコードです。

void CreateIcon (int areaNo, int x, int y)
{
	int posX = 
				x * 148 
				+ (int)(Icon.transform.localScale.x / 2) 
				+ OFFSET_X 
				+ (areaNo * Constants.DISP_W) 
				+ ICON_OFFSET_X;

	int posY = 
				(-y * 148) 
				- (int)(Icon.transform.localScale.y / 2) 
				+ ICON_OFFSET_Y;

	var obj = (GameObject)
				Instantiate (
					Icon, 
					new Vector3 (posX, posY, 1), 
					Quaternion.identity
				);

	〜〜 以下略 〜〜

}

久々に紐解いてみましたが、
やや複雑な計算ですね…


自分で作ったのに、どこで何しているのかよくわからないです。
148ってなんだよ…


リファクタリングがきちんとできていない証拠ですね(--;

x座標

まずはposXの座標をどう求めてるか見ていきます。

x * 148 

148はアイコン部分の基本幅になります。
なので、単純に並べるだけなら、この部分だけでOKで、
148の値を適当に調整すればなんとなくの位置に並べることも可能です。

(int)(Icon.transform.localScale.x / 2) 

Iconは、Iconのオブジェクトになります。
アイコンとアイコンの間隔をアイコンの大きさの半分に
したかったみたいです。

OFFSET_X

5000で設定されていました。
前回説明してましたが、アイコン部分と情報説明部分を
別のカメラで描画しており、それぞれが間違って被らないよう
Xを遠くに設定していたようです。

Yで距離をつけたほうが、Editor上で近くなるし、
今回はX位置を決めるのが煩雑だったので
ちょっと設計ミスだったかもです。

(areaNo * Constants.DISP_W)

エリアごとの幅調整をしています。
1エリアと、2エリア目は画面スクロールで別画面になるため、
アリア内でのアイコン幅より若干広めに取っておく必要があります。

ICON_OFFSET_X

今表示されてる画面の左からどれくらいオフセットを取るか
という数値です。


以上を足すことにより、X座標が求まりました。
一応、全部目的があって複雑になってたようです。

y座標

y座標は大分シンプルです。
また、x座標で既にでてきた考えと同様なので、簡潔に行きます。

(-y * 148) 

基本位置。
ただし、Unityのワールド座標のy値は
標準のカメラの位置では、画面下がマイナスになってるので、
マイナスを掛ける必要があります。

いつもこの辺がややこしいなぁと感じているんですが、
よく考えたら、カメラを上下反転させれば、
感覚的なy値と実際のy座標をあわせれるのでは!?
と今思いつきました。
今度やってみます。


(int)(Icon.transform.localScale.y / 2) 

アイコンの高さ間隔

ICON_OFFSET_Y

画面上部からのオフセット値

オブジェクト生成

	var obj = (GameObject)
				Instantiate (
					Icon, 
					new Vector3 (posX, posY, 1), 
					Quaternion.identity
				);

予め計算したx,y座標位置に、オブジェクトを生成。
今回は2D画面を想定してるので、z値は固定です。


座標を決めるのも意外と大変でした。


次回は、アイコン部分の生成です。

過去のシリーズ