◎ HowToMake全部見せます企画 ~Unity版~ ◎


4ページ目

§9 スクリプトのことについて深く考える
これからスクリプトを書くにあたって、
あの初めに書いたざっくりとした文章をもう少し細かく分けて考えないと、
スクリプトをかけないので、考えましょう。

1.ターゲットの数の管理
・ターゲットの数は必ず10個
・全部消えたらゲームクリア

2.配置の管理
・ランダムに10個×3種類=30個を配置する
・重なるとまずい?(要確認)

3.ターゲットの決定
・ゲーム開始時に
・ランダムで決定

4.スコア管理
・開始からクリアまでの時間をはかる
・画面上に表示させる

5.ゲーム終了
・ゲーム終了後に
・クリアまでの時間をツイートすることができる
・ゲームを初めからやり直すボタンが必要

6.追加の仕様
・ターゲットじゃないものをクリックするとゲームオーバーにする
・ゲームオーバー後もツイートできるようにする
・はじめからやり直すボタンが必要

まぁ、6の件は1と5に分解できるんだけど、追加なので追加に書きました。

先に2から解決しよう。



§10 配置の管理
「ランダムに配置するときに、オブジェクト同士が重なるとまずいか?」を検証。
……。あんまり深く考えなくてもいいのかな。

30個を手動で配置してみると、こんな感じになった。
ゲームを動かしてみると、まぁいい感じになってくれるんじゃないかしらね。
ターゲットのサイズはこんな感じでよさそう。
画面の上から落ちてきてほしいなぁ。
壁のない上に配置して落としてみたけど、同じ大きさで同じ重さで同じ重力なので、
同じように落ちてきて、壁のないところで横にこぼれたりしないみたいだ。
安心。

1.どれぐらいの範囲でばらけてほしいか
ランダムで配置するには、どのくらいの範囲でばらけてほしいかを考えなくっちゃ。
さっき配置した上下左右端のポジションを読む。
範囲は
 x:-2.7~2.7
 y:8.6~18.6
っぽいので、その範囲の中で10×3=30個を配置することにする。

今はAだけだから、10個ランダムで配置できればよい。

2.スクリプトを書く

新しく「TargetCtrl」というスクリプトを作る。
このスクリプトからターゲット達へ指示を出してもらおう。
作ったらそれをダブルクリップして…。


1から10まで繰り返してね、というのはfor文という呪文を唱えます。
プログラム的には0~9。
えーっと、Transformの数字は少数だから、float型で、

for (int i=0 ; i<10 ; ++i) {
// ランダム数を Range(a,b)<aからbの間で>生成
float yoko = Random.Range(-2.7f, 2.7f);
float tate = Random.Range (8.6f, 18.6f);
// 「preA」を(x,y,z)の座標に貼る(最後のは確か深度とかいうやつだった気がする)
Instantiate(preA, new Vector3(yoko, tate, 0.0f),Quaternion.identity);
}

こんなかんじかな。
今は始まりと同時に配置してくれればいいから、
void Start(){ }の中に書く。
あとで別なタイミングで配置してほしくなったら、移動させよう。

で、書くと、preAが赤文字で、エラーが出ていることがわかる。
スクリプトからすればpreAって誰のことかわからないから。
事前に「preAとはこれです!」と教えないといけない。
Startの前のところに

public GameObject preA;

と書く。こういうゲームオブジェクトを使います、ということ。
publicと書いておくと、Unityの右のところでpreAの実際の中身が何なのかを直感的に指定できる。

さてUnityに戻って。
さっき手動で配置しておいたプレハブを全部消して、新しく空のオブジェクトを作る。
名前を「TargetC」として、これにスクリプト「TargetCtrl」を付ける。ついでにプレハブ化しておく。
右のところに、プレハブの時はScriptの名前しか欄がなかったけど、
その下に「Pre A」という欄ができてる。ここの欄に、プレハブのフォルダからpreAをドラッグ。
これで、さっきのfor文の中のpreAとはどのオブジェクトなのか、を指定することができた。

これで本当に10個はってくれるんかいな。
心配なので再生してみよう。
おっ、いいんじゃない? できたできた。
数もちゃんと10個だし。

これで配置は完了。



§11 ターゲットの数とゲームクリア
今はAしかないけど、とりあえず、Aの残りがゼロ個になったらゲームクリアということにする。
TargetCtrlに、残りの数を管理してもらう。
§10で書いたGameObjectの下に
private int ZanA = 10;
と書く。別にprivateを指定しなくてもC#は基本的にprivateらしいんだけど、privateのつづりを覚えるために書く。
いまだにトゥルーのつづりを間違えてtureと書く程度に頭が弱いので…。
ZanA(残Aの意)は整数なので、int型。0になったらクリアという判定にするために、初期値として10を持っていてもらう。

1.クリックしたら残量を減らす
preAがクリックされる→残Aを1減らす→preAが消える
という流れになる。
もうちょっと詳しく書くと、
preAがクリックされる→preAからTargetCtrlへ「残Aを1減らしてくれ」と依頼→preAが消える
となる。
スクリプトAからスクリプトBに依頼を出すには「Sendmessage」を使用する。
ここで依頼が出せる内容は「○○という関数を動かしてね」なので、
正式な依頼文は「クリックされたから○○やっといて!」という丸投げ方式。


<「TargetCtrl」に書く文>
Aがクリックされた時のため用の関数を新しく追加する。
void clA(){
ZanA -= 1;
Debug.Log ("残A:" + ZanA);
}
デバッグ.ログというのは、Unityの下のところの「Consol」に書いてね、という命令文。

<「SpreA」に書く文>
まず初めにTargetCtrlが付けられているTargetCを見つけてもらって、
それからクリックされたときに「clAを実行してくれ」と言う。

ここでさっき使ったpublic GameObject戦法を使いたいけれども、
この戦法が使えるのは、シーン上に配置されているものだけ。
preAは「後からシーンに貼り付けられる」ため、使えない。残念。
ということで、面倒臭いけど違う方法をとる。

Startの上に
private GameObject TC = null;
と書く。TCは空のゲームオブジェクトだよ。
Startの中に、
TC = GameObject.FindGameObjectWithTag ("TargetC");
と書く。「TargetCというタグがついたゲームオブジェクトを探して、TCの中身にしてね」という意味。
タグってなんだよ!
右のところの上にTagってあるでしょ!

TargetCなんていうタグはないので、Add Tags...から追加する。
TargetCというオブジェクトにTargetCというタグがつきました。
では、
void OnMouseDown(){
TC.SendMessage ("clA");
Debug.Log ("消したよ");
Destroy (this.gameObject);
}
こう書けば、TCに「clAを実行してね!」と遺言を残して死んでいくわけだ。
ここにデバッグログを入れておくことで、消した側がちゃんと動作してるかどうかを見ることができると思うきっと。


さっそく再生だ!

うまくいったぞ!
やべー、もうゲームできたも同然ジャン!(三回目)

ここで、もう「消したよ」メッセージはなくてもいいので、消したりコメントアウトしてもよい。


制作時間は、再開してから2時間、かな。
次行こう!






←前へ 目次 次へ→