i-school - 強制横スクロールゲーム 発展3

ータイトル演出の追加−


 この手順ではタイトル表示中の演出を追加します。タイトル用に TitleObject 群(ゴール地点と橋のゲームオブジェクト)を追加し、アニメ演出させます。
タイトルをクリックしてゲームがスタートすると同時に、ゴール地点を画面から右側に移動させます。
このように演出することによって、ゴールが右側にあることをユーザーに伝えます。

<タイトルに TitleObject(ゴール地点と橋)を追加表示>



<実装動画 橋のオブジェクトをアニメ演出>
https://gyazo.com/9a02f31a2801c92fdb0b2a1e17bd5dc2


<実装動画 タイトル表示中に画面をクリック(タップ)したら TitleObject を移動させる>
https://gyazo.com/b71f68030304a751e24984d2940c4dc9


 ■ TitleObject を作成してアニメ演出させる
 ■ スクリプトを使って、タイトル表示中にクリック(タップ)したら TitleObject を移動させる



 新しい学習内容は、以下の通りです。

 ・Startメソッドの戻り値をvoidからIEnumerator型にして使用する処理
 ・WaitUntil クラス


■ TitleObject を作成してアニメ演出させる

1.設計


 現在のタイトル表示に、新しくオブジェクトを追加して、タイトル表示の見栄えをよくします。

 すでに製作済の GoalHouse ゲームオブジェクトと、インポートしたアセットにあるオブジェクトを利用して
これらのオブジェクト群を TitleObject としてまとめて管理を行います。
 
 ゲームを実行したら、スクリプトを利用して橋のゲームオブジェクトを上下に移動させて、ゲームへの期待感を高めます。

 ゲームオブジェクト群の製作と、橋のゲームオブジェクトを上下移動させるスクリプトの作成を行います。

 ここでは順番に作成を行っていきますが、自分で実装できそうな部分については、教材を参考程度に利用してください。
動画をみて、どのように製作していけばいいのか、イメージを膨らませてみるといいでしょう。


2.TitleObject ゲームオブジェクトを作成する


 ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Create Empty を選択します。
新しい空のゲームオブジェクトが作成されますので、名前を TitleObject に変更してください。


ヒエラルキー画像



TitleObject ゲームオブジェクト インスペクター画像



 画面の中央位置より、若干、左下よりに配置します。インスペクター画像は画面の解像度によって変わりますので、参考程度にしてください。


Sceneビュー画像



TitleObject ゲームオブジェクト インスペクター画像



3.TitleObject ゲームオブジェクトの子オブジェクトとして GoalHouse ゲームオブジェクトを追加する


 Prefabs フォルダ内にある GoalHouse ゲームオブジェクトをドラッグアンドドロップして、TitleObject ゲームオブジェクトの子オブジェクトとして追加します。
 

ヒエラルキー画像



 不要なコンポーネントを削除、あるいは無効にします。

 BoxCollider2D コンポーネントと GoalHouse スクリプトをリムーブするか、チェックを外して無効にしてください。

 続いて、位置を調整します。Gameビューを見ながら、床部分がスタート地点と同じ高さになるように、
また、画面の右端になるように配置を行ってください。

 インスペクター画像を載せますが、画面の解像度によって位置は変わりますので、参考程度にしてください。


SceneビューとGameビュー画像



GoalHouse ゲームオブジェクト インスペクター画像



 そのほかは変更ありません。続いて、橋のゲームオブジェクトを作成します。


4.TitleObject ゲームオブジェクトの子オブジェクトとして Nature_props_38 ゲームオブジェクトを追加する


 ゲーム画面のスタート地点の床とゴール地点の床をつなぐためのゲームオブジェクトを作成します。
ここでは橋のゲームオブジェクトのプレファブを利用していますが、他のゲームオブジェクトでも構いません。


パス
Assets/Nature_pixel_art_assets/Prefabs/Nature_props/Nature_props_38.prefab


フォルダ画像



ヒエラルキー画像




 ゲームオブジェクトの名前はそのままでもよいですし、分かりやすく Bridge などに変更していただいても構いません。

 最初に、SpriteRenderer コンポーネントを確認し、Order in Layer の値を 2 に変更してください。

 続いて、ゲームオブジェクトのサイズと位置を調整します。Gameビューを見ながら、スタート地点の右側に配置してください。
今回利用しているゲームオブジェクトの場合、Scale を (3, 3, 3) に変更して配置していますが、選択したゲームオブジェクトによって適宜調整してください。
下記のインスペクター画像は参考程度に利用して、このゲームオブジェクトが3〜4個並ぶ前提で配置を考えてください


Nature_props_38 ゲームオブジェクト SceneビューとGameビュー画像



Nature_props_38 ゲームオブジェクト インスペクター画像



 つづいて、ゲームオブジェクトを複製する前に、スクリプトを作成します。
そちらのチェックが完了して完成した橋のゲームオブジェクトを元に、2個目以降の橋用のゲームオブジェクトを複製します


5.FloatingFloor スクリプトを作成して、Nature_props_38 ゲームオブジェクトにアタッチする


 橋用のゲームオブジェクトをランダムな高さに上下に移動させる制御処理を、スクリプトを作成して行います。
DOTween の機能を利用して移動制御を行っていますが、処理を見る前に、自分で書いてみて実装をしてみてください。


FloatingFloor.cs



 スクリプトが完成したら、Nature_props_38 ゲームオブジェクトにドラッグアンドドロップしてアタッチします。


Nature_props_38 ゲームオブジェクト インスペクター画像



 以上で設定は完了です。


6.ゲームを実行して動作を確認する


 ゲームを実行し、橋用のゲームオブジェクトが上下にふわふわと移動するか、確認を行ってください。


<実行動画>
https://gyazo.com/571f1512196472447233adc7d1642db9


 問題なければ、このゲームオブジェクトを複製します。


7.Nature_props_38 ゲームオブジェクトを複製して、少しずつ高さをずらして配置する


 それでは、Nature_props_38 ゲームオブジェクトを複製して、少しずつ高さをずらして配置してください。
スクリプトによってランダムな高さに上下移動するので、すべて同じ高さよりも少しずつずらしておいた方が見栄えが良くなります。
この例では3つ並べています。


ヒエラルキー画像



SceneビューとGameビュー画像



参考 インスペクター画像





 以上で完成です。


8.ゲームを実行して動作を確認する


 すべてのオブジェクトを設置しましたので、ゲームを実行して動作を確認してみましょう。
それぞれのオブジェクトがランダムで上下移動していれば制御成功です。何回か起動を繰り替えて動作を確認してみてください。


<実行動画 橋のオブジェクトをアニメ演出>
https://gyazo.com/9a02f31a2801c92fdb0b2a1e17bd5dc2


 続いて、タイトル表示中に画面をクリック(タップ)したら、TitleObject が画面外に移動する制御を実装します。




■ スクリプトを使って、タイトル表示中にクリック(タップ)したら TitleObject を移動させる

1.設計


 タイトル表示の制御は UIManager スクリプトによって行っています。こちらのスクリプトには、タイトル表示状態を管理している変数がないため、
タイトル表示が終了しているかどうかについては、確認を行うことが出来ない状態です。

 まずは、このタイトル表示が現在どのような状態かを管理できるようにする必要があります。色々な方法がありますが、最もわかりやすいのは bool 型で制御を行うことです。
false のときはタイトル表示中で未クリック状態、true のときはタイトル表示中でクリックされた状態、というようにすれば、どのような状態であるかを管理することが出来ます。

 TitleObject ゲームオブジェクトの制御用には新しい TitleObjectController スクリプトを作成し、そちらで制御を行うとよいでしょう。

 このスクリプト内で UIManager スクリプトに新しく用意した bool 型の管理用変数を確認し、クリックされた、と判断した場合に
TitleObject ゲームオブジェクトを画面の右端へと移動させるように制御を行います。

 TitleObjectController スクリプトが外部のスクリプトである UIManager の変数を確認する方法は色々あると思います。
Update メソッドで監視する、while 文を利用して監視する、クリックされたら、TitleObjectController スクリプトに用意してあるメソッドを呼び出すようにする、など、
実装する際の方法は自分で考えてみてください。

 今回の実装例のロジックとしては、以下のような流れになります。

 ・UIManager スクリプトに bool 型の isTitleClicked 変数を false で宣言する
  この値は UIManager スクリプトの OnClickTitle メソッド内で true になるようにする
   ↓
 ・TitleObjectController スクリプトの Start メソッド内で UIManager スクリプトの isTitleClicked 変数が true になるまで処理を中断しておく
   ↓
 ・タイトル表示中に画面をクリックすると、UIManager スクリプトの OnClickTitle メソッドが実行されて、isTitleClicked 変数が true に切り替わる
   ↓
 ・TitleObjectController スクリプトの Start メソッド内の中断されていた処理が再度動き始めて、TitleObject ゲームオブジェクトを移動させる命令が実行される
   ↓
 ・TitleObject ゲームオブジェクトが画面のクリックによって、画面外に移動するという処理が完成する


2.UIManager スクリプトを修正する


 上記のロジックをイメージしながら、どのような変数の宣言が必要なのか、自分なりの実装を行ってから処理を確認してみてください。
もちろんこれは一例ですので、実装が問題なくできている場合には「こういう方法もあるのか」という、復習教材として活用をしてください。


UIManager.cs

 <= クリックすると開きます。



 スクリプトを修正したら、UIManager ゲームオブジェクトよりインスペクターを確認します。
新しく追加した変数が表示されていれば問題ありません。この値は false のままでよいです。


UIManager ゲームオブジェクト インスペクター画像



3.TitleObjectController スクリプトを作成する


 先ほどのロジックの部分で説明したように、UIManager スクリプトの isTitleClickaed 変数を確認する方法としては
コルーチンメソッドにした Start メソッド内に、WaitUntil メソッドを実行して、一時中断処理を利用しています。

 こちらも UIManager スクリプトと同じように、自分の実装したものと確認していただくとよいでしょう。


TitleObjectController.cs

 <= クリックすると開きます。



4.<WaitUntil クラス>


 WaitUntil クラスは、コルーチン内で命令できる待機処理です。yield return をつけて new (インスタンス)します

 WaitUntil クラスにはコンストラクタ・メソッドがあり、インスタンスされると、引数で指定した条件を満たすまで、処理を一時中断して待機させることが出来ます。

  // 引数で指定している条件を満たすまで、ここで処理を一時中断して待機する
  yield return new WaitUntil(() => uiManager.isTitleClicked == true);

 今回の場合の条件は、【UIManager スクリプトにある isTitleClicked 変数が true になったら】という条件になります。
この条件は、タイトル表示中に画面をクリックすることで true になります。処理は再度再開されて、次の処理に移ります。

 次の処理は MoveTitleObject メソッドになりますので、一連の処理としてみると、
タイトル表示中にクリックされたら TitleObject を移動するメソッドを呼び出す】となります。
 
 このメソッドによって、クリックされるまで(条件を満たすまで)移動させる処理が一時中断されているので、そういった待機させる処理に利用することができるメソッドになります。

参考サイト
Unity公式スクリプトリファレンス
WaitUntil
https://docs.unity3d.com/ja/current/ScriptReferenc...


5.Startメソッドの戻り値をvoidからIEnumerator型にして使用する処理


 通常の Start メソッドの戻り値は void ですが、用途に応じて戻り値を IEnumerator型 に変更して利用することができます。
その場合、通常と同じようにゲームの実行と同時にStartメソッドが呼ばれる部分は変わりませんが、
コルーチンメソッドとして機能するようになりますので、Start メソッド内で遅延処理や一時中断処理などの yield を利用した処理を実装することが可能になります

  IEnumerator Start() {   // <=  ☆ 戻り値が違うので注意する

      // 引数で指定している条件を満たすまで、ここで処理を一時中断して待機する
      yield return new WaitUntil(() => uiManager.isTitleClicked == true);
        
      // TitleObject を移動
      MoveTitleObject();
  }

 今回のケースではStart メソッド内に、上で説明をした、画面のクリックを行うまで一時中断する WaitUntil メソッドの処理があります。
こちらの処理を終了してから次の処理へと移る、という順序立てた制御を行いたいため、この処理を実装し、Start メソッドをコルーチンメソッドとして利用しています。


6.TitleObject ゲームオブジェクトに TitleObjectController スクリプトをアタッチし設定を行う


 TitleObject ゲームオブジェクトに、TitleObjectController スクリプトをドラッグアンドドロップしてアタッチしてください。


TitleObject ゲームオブジェクト インスペクター画像



 アサイン情報が2つ表示されますので、適宜なゲームオブジェクトをアサインして登録を行います。
どのゲームオブジェクトの、どのスクリプトを制御するのか、必ずイメージを持ちながら処理を行いましょう。


TitleObject ゲームオブジェクト アサイン後のインスペクター画像



7.ゲームを実行して動作を確認する


 すべての手順が終了しました。ゲームを実行して制御できているか、動作を確認します。

 タイトル表示中に画面をクリック、またはタップすると、Game Start の表示に合わせて、TitleObject ゲームオブジェクトが
画面の右端へ移動し、画面から見えなくなってから破壊されれば制御成功です。


<実行動画 タイトル表示中に画面をクリック(タップ)したらゴール地点を移動させる>
https://gyazo.com/b71f68030304a751e24984d2940c4dc9


 以上でこの手順は終了です。