各ぷよに付けるスクリプトを記述しよう2
このページでも前回に引き続き、各ぷよオブジェクトに付けるスクリプトを記述していきます。前回箇条書きで纏めましたが、ぷよスクリプトのお仕事は以下の通りでしたね。
・ぷよセットオブジェクト(親)が消滅するまでは、本スクリプトは休み
・コンビ解散直後、各ぷよごとに地面 or 他のぷよの上に着地するまで落下
・ぷよの落下が完了次第、同色ぷよが4個以上隣り合っていたら消滅
(↑監督スクリプトで記述)
・ぷよ消滅により浮かんでるぷよがあれば、再び地面 or 他のぷよの上に着地するまで落下
前回、箇条書き1、2つ目の挙動をスクリプト化していきました。今回は、残り1つのぷよ消滅により浮かんでるぷよがあれば、再び地面 or 他のぷよの上に着地するまで落下、をスクリプトに記述していきます。
今回書いていくスクリプト文自体は、そこまで難しいものではありませんが、このメソッドが有効になったら、この変数がこう変わって、このif文が再びtrueになって…といった具合に、前回書いたスクリプト文との相互作用による、ゲーム実行中の各変数の移り変わりを冷静に考えていく必要があります。つい混乱しそうな話になりますが、決して頭をパンクさせずに、落ち着いて考えていきましょう!よろしくお願いします!
ぷよ消滅により浮かんでるぷよがあれば、再び地面 or 他のぷよの上に着地するまで落下
今回の話は、同色ぷよが4つ以上隣り合って消滅した後の話になりますが、このぷよ再落下の話は、監督スクリプト上でのぷよ消滅の話と深く関連します。深く関連がある監督スクリプト側の解説ページはこちら(制作手順5-5)の後半になります(ナンバリング的にかなり後ですが、現時点で読んでも大丈夫です!)ので、併せてお読み頂けると、より理解が深まると思います!
監督スクリプト側の状況を説明しますと、同色ぷよが4つ以上隣り合って消滅した後、監督スクリプトからフィールド上に残っている全ぷよに対し、「お前ら全員、num=0にリセットじゃ~」という指令が出ます。
前回の終わりの方で説明しましたように、変数numは落下完了を表す変数で0なら落下未完了、1なら落下完了、という値を取ります。よって、監督スクリプトから指令が下るまでは、フィールドにあるぷよは全てnum=1です。
しかし、ある日突然監督スクリプトからムリヤリnum=0に強制変換されてしまうのです。そして、num=1の間は特に機能していなかったUpdateメソッドが、num=0になった瞬間から再稼働します!
Updateメソッドの詳細については、前回の後半で解説した通りです。
よって、num=0になったとしても、地面のスグ上だったり下に浮いてるぷよが無ければ、特にこれ以上落下することはなく、すぐにnum=1に戻ります。しかし、例えばすぐ下のぷよが消えてしまった場合は、そうはいきません。地面 or 他のぷよの上に着地するまで再落下し続け、落下が完了したらまたnum=1に戻ります。
こんなストーリーが実現出来るよう、必要なスクリプトを書いていきます。繰り返しになりますが、再落下の機能については前回のUpdateメソッドを再活用します。つまり、追加で必要なスクリプトは「監督スクリプトからの指令でnum=0に変換される」という部分だけになります!別のスクリプトから呼び出されるメソッドを書く場合、メソッド名の最初に「public」と書いておけば良いのでしたね!
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//ぷよ消去後に一斉落下するため、全ぷよのthis.num=0(監督スクリプトより呼び出し) public void numreset () { int i = 0; this.num = 0; //落下を再開(Updateメソッドに従う) //注意:現時点でのフィールド中のぷよ位置をここで再調査 this.puyos = GameObject.FindGameObjectsWithTag("puyo"); foreach (GameObject puyo in this.puyos){ //丸め誤差解消(フィールト中の全ぷよの位置) this.puyox[i] = Mathf.RoundToInt(puyo.transform.position.x * 10.0f) / 10.0f; this.puyoy[i] = Mathf.RoundToInt(puyo.transform.position.y * 10.0f) / 10.0f; i++; } } |
スクリプト中にも書きましたが、注意としては、num=0となったこの瞬間に、改めてフィールド中の全ぷよ位置を再調査する必要があります。詳しくは下の絵で説明します。
上図での黄ぷよが消滅した時点で、改めて残っている全ぷよの位置情報を更新(図右上)しておけば、消えた黄ぷよの上にある赤ぷよとしては、「自分の下にある黄ぷよが無くなった!」ことを理解し、下に落ちてくれます。しかし、位置情報の更新が無ければ(図右下)、赤ぷよの立場からすれば下の黄ぷよは残ったままだと思い込んでいるので、浮いたままになっていまう、ということです。細かい話ですが、ゲームを正しく進めていく上で、非常に重要な手続きとなります。
更に言いますと、ぷよが落ちている最中についても、何度も(1フレーム毎に)全ぷよの位置を再調査する必要があります。
何故かと言いますと、コンビ解散後のぷよ落下では自分自身だけが落下しているのに対し、再落下の時は周りのぷよも同時に落下しているからです。よって、複数のぷよの位置が常に変化し続けますので、落下完了の判定を正しく下すためには、1フレーム毎に全ぷよの位置を調査し続ける必要がある、という事情になります。
つまり、前回書きましたUpdateメソッドの一部を書き換える必要があります!以下では、if(親がいない場合)の中身全体を再度書いておきます。実際に追加するのはたった2行です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
if(transform.root.gameObject == gameObject){ //コンビ解散後の挙動を記述 if(nowy == -5.5f) { this.num = 1; //落下完了をお知らせ return; } i = 0; foreach (GameObject puyo in this.puyos) { //丸め誤差解消(フィールト中の全ぷよの位置)【以下2行を追加】 this.puyox[i] = Mathf.RoundToInt(puyo.transform.position.x * 10.0f)/10.0f; this.puyoy[i] = Mathf.RoundToInt(puyo.transform.position.y * 10.0f)/10.0f; if(nowx == this.puyox[i] && nowy == this.puyoy[i] + 1.0f) { this.num = 1; //落下完了をお知らせ return; } i++; } //落下完了していないので引き続き落下 transform.Translate(0,-1.0f,0, Space.World); } |
最後に
これで各ぷよに付けるスクリプト解説は以上になります。ゲームのスクリプトを書こうと思うと、起こりうる可能性を全て洗い出し、いかなる場合でも問題無く動くようにプログラミングしなければなりません。可能性の洗い出しにモレがあると、作者の想定もしていないような挙動が突然起こります(いわゆるゲームのバグという奴です)。
今回、再落下時に全ぷよ位置の再調査を行わないと、ぷよが浮いたままになる、という話をしました。これもバグの一種です。ゲーム制作時に、もしこのようなぷよが浮いた現象を目の当たりにしても、決して慌てることなく、「あ、浮いてるやん(笑)、どこがマズイんやろ?」という冷静な気持ちでスクリプトを根気よく見直して(デバッグして)いくことが大切になってきます。
何度も見直しても原因が分からず、バグが取れない…私ワガハイも勿論経験済ですし、その時は大変イライラしますが、そんな時はコーヒー飲んだり、身体を動かしたりして気分転換することも大切になってきます!根気よくいきましょう!
コメント
組ぷよの生産工場のプログラムを教えてください
返信遅くなり申し訳ございません。また、リクエスト大変ありがとうございます!
現在ページを鋭意作成中ですので、しばらくお待ち頂きますよう、よろしくお願いします。