i-school - 2Dタワーディフェンス 手順27
 キャラを配置するためのコスト機能の実装を行えるようにするために、時間の経過によるカレンシー(お金)の要素の実装を行っていきます。


<実装動画>
動画ファイルへのリンク


 カレンシーの要素がゲーム内に加わることにより、【この値を消費することでキャラの配置を行う】という新しい機能の実装も可能になります。

 現在はどのキャラでも自由に配置が可能であるため、カレンシー要素によって配置する際にプレイヤーの選択肢が増えることにつながります。
キャラのデータに新しくコストを追加し、性能差を考慮したコスト値を設定しておくことで、「コストの高い高性能キャラ」や「コストの低いもののすぐに配置が可能なキャラ」といった形で特徴付けをすることが出来ます。
これは遊び方の提案にもつながるので、考えずに配置しても遊べるが、しっかりと考えて吟味して配置をする、というプレイスタイルを提案出来ます。

 以下の内容で実装を進めていきます。

手順27 ーカレンシー機能の実装ー
45.GameData スクリプトと UIManager スクリプトを作成する。Canvas 内にカレンシー表示用のゲームオブジェクトを配置する
46.GameManager スクリプトを修正し、時間の経過に合わせてカレンシーが加算される機能を実装する



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

 ・ロジックを考えて処理を実装する



45.GameData スクリプトと UIManager スクリプトを作成する。Canvas 内にカレンシー表示用のゲームオブジェクトを配置する

1.設計


 ほとんどのタワーディフェンスゲームでは、ゲーム内の時間が経過するごとに、カレンシー(通貨)が蓄積されていき、
それを各キャラごとに設定されているコスト分消費することによって、キャラをゲーム内に配置できるようになっています。
(各用語はゲームにより異なりますが、システム的な挙動は同じです。カレンシーがマナという名称であったりします)

 すでにキャラを配置する処理は出来ていますので、この部分にコストの確認と支払いの機能を追加し、コストを支払ってはじめてキャラを配置できるように修正を行います。

 今回の手順の設計では、このコストの支払いに利用できるカレンシーの要素を実装することが目的です。
次の手順で、このカレンシーを利用して、コストを支払ってキャラを配置する処理を実装するようにしていきます。

 このように新しい機能の実装は、複数の異なる機能の実装の積み重ねと、それらを上手く組み合わせてロジックを作ることによって実装されます。

 まずはカレンシーの要素について、処理の全体の流れを考えていきます。その後、設計のロジックを考えましょう。
スクリプトを書くのは、これらが完成し、処理の全体が出来上がってからになります。
イメージを作っていくことが非常に重要になりますので、想像力をふんだんに働かせてください。



 カレンシーを管理するには、カレンシーだけではなく、それに関わるいくつかの情報が必要です。また、この情報をどのクラスに用意して管理させるかも一緒に考える必要があります。
特にカレンシーを管理しているクラスを参照することが困難であると、スクリプトからカレンシーを参照することが難しくなるためです。
そのため、カレンシーを利用したいクラスがどの位あるのか、その場合、そのクラスにカレンシーの情報があったら便利か、という観点で設計をしていく必要があります。

 カレンシー、および、カレンシーに関連する情報をまとめます。

 ・カレンシー      ゲーム内の時間の経過に合わせて加算され、コストを支払う際に充当される値
 ・タイマー       ゲーム内の時間の経過を計測する値
 ・タイマー目標値    ゲーム内の時間の経過をタイマーで計測した際、タイマーの値が目標とする値。この値を超えることで、カレンシーに加算処理が入る  
 ・カレンシーの加算値  タイマーの値がタイマー目標値を超えるたびに、カレンシーに加算される値
 ・カレンシー最大値   カレンシーの最大値。この値以上には加算されないように制御する

 値をどのように利用するかは設定しました。
あとは、これらの情報を使ったロジックを考えて、カレンシーの値がゲーム内の時間経過に合わせて加算していく処理を考えてみてください。

 これらの情報は、すべて同じクラスに管理させる、というものでもありません。
この値はどのクラスにあればいいか、という風に考えながら処理とつなげていく必要があります。
例えば、タイマーの値は、すべてのクラスで利用する情報ではありませんので、実際にゲームを管理している GameManager に用意する、といった形です。



 次は、先ほどのカレンシーの情報を変数として作成する場合には、どのような型で、どのような変数名にするべきかを考えていきます。
参考までにご紹介しますが、ご自分のわかりやすい名称を採用してください。

    [Header("カレンシー(コスト用の通貨)")]
    public int currency;

    [Header("カレンシーの最大値")]
    public int maxCurrency;

    [Header("タイマー目標値(カレンシー加算までの待機時間)")]
    public int currencyIntervalTime;

    [Header("カレンシーの加算値")]
    public int addCurrencyPoint;

    int timer;



 続いては、これらの値を使ったロジックの作成です。
どのようなロジックにすれば、これらの情報を元にして一定時間経過後にカレンシーの値を加算していく処理が実装できるかを考えてみてください。

 主な手法としては、Update メソッドを活用する方法と、コルーチンメソッド内で while 文を活用する方法があります。
while 文の場合は yield return null の処理を組み合わせることにより、疑似的な Update メソッドのようなフレーム単位でのタイマーの計測が可能になります。
特に while 文を利用する場合には、無限ループ状態の発生によってゲームがフリーズしないように気を付けてください。

 紙などにロジックをフローチャートのようにして書いていくと処理を可視化して確認できますので、ロジックを作りやすくなると思います。
また、このロジックを組み込みたいスクリプトの候補が浮かんでいるのであれば、そのスクリプト内にフローチャートのコメントを順番に書いておくといいでしょう。
実装したい処理を細かくコメント化しておくと、プログラムを作っていく際に役立ちます。



 カレンシーの値を一定時間ごとに加算する処理のロジックが完成したら、次は、その情報をゲーム画面に表示する処理を考えてください。
内部的にカレンシーの値が加算されていても、ゲーム画面上に現在のカレンシーの値が表示・更新されていないとユーザーはカレンシーを認識できません。
よって UI としてゲーム画面に表示することが大切です。

 表示する位置や、表示を更新するタイミングなども考慮してください。例えば、一定時間ごとにカレンシーの値が加算されるのであれば、
Update メソッドで常時カレンシーの表示を更新する必要はありません。加算されたり、コストが支払われたりして、カレンシーの値に変更があったタイミングで
画面のカレンシーの値が更新される方が適切な処理であるといえます。そういった観点で処理の更新についても考えてみてください。

 UI の管理については、カレンシーの加算処理を行っているスクリプト内でもよいですし、新しく UI 管理用のマネージャークラスを作成してもいいです。
今後、UI の表示が増えることを考えた場合には、UI 管理用のマネージャークラスを作成しておいた方が管理はしやすくなります。



 ここまで完成したら、あとは実際にロジックをプログラムとして組み込んでいく作業になります。

 ロジックを使った処理を作るために、必要になる情報を作成することから始めます。
今回であれば、カレンシーに関連する値をスクリプト内に新しく追加する部分です。
既存のスクリプトに書くのか、新しくクラスを作るのかはすでに決まっているはずですので、そちらにカレンシー関連の変数を追加します。
この部分を完成させてから、最後に、この値を利用したロジックを作成していきます。

 なぜなら、必要な情報がなければロジックを組むことができないためです。

 続いて、UI 関連の処理に移ります。カレンシーの値を表示するゲームオブジェクトを作成します。
また、UI 管理用のマネージャークラスを作成を行います。


2.GameData スクリプトを作成する


 今回はカレンシーの関連の情報をシングルトンで作成する新しいクラスに管理する方式で実装を行っています。


GameData.cs

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


 スクリプトを作成したらセーブを行います。


3.GameData ゲームオブジェクトを作成して、GameData スクリプトをアタッチし、設定を行う


 作成した GameData スクリプトをアタッチするためのゲームオブジェクトを作成し、アタッチして設定を行います。
ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Create Empty で新しいゲームオブジェクトを作成します。
名前を GameData に変更して、GameData スクリプトをドラッグアンドドロップしてアタッチしてください。


ヒエラルキー画像



インスペクター画像



 これらの設定は変更できますので、まずは上記の画像を参考にしてカレンシーの関連の初期値を設定しておいてください。

 以上で GameData に関する処理は完成です。


4.Canvas ゲームオブジェクト内にカレンシー表示用のゲームオブジェクト群を作成する


 カレンシーの現在値をゲーム画面に表示したいので、UI としてカレンシーの値を表示するためのゲームオブジェクトを作成します。
Canvas ゲームオブジェクト内に自由に作成してみてください。下記は参考例です。

 自分が遊ぶ立ち場になって、どの位置に、どの位の大きさで表示されていればいいかを考えて配置してみてましょう。


ヒエラルキー画像



Sceneビュー画像



Game ビュー画像



 完成したら、このゲームオブジェクトにアタッチされている Text コンポーネントを制御するための処理を作成します。
今回は先のことも考えて UI 管理用のマネージャークラスを作成して、この制御処理を記述しています。


5.UIManager スクリプトを作成する


 UI 管理用のマネージャークラスを作成します。


UIManager.cs

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

 
 スクリプトを作成したらセーブを行います。


6.UIManager ゲームオブジェクトを作成し、UIManager スクリプトをアタッチして設定を行う


 作成した UIManager スクリプトをアタッチするためのゲームオブジェクトを作成し、アタッチして設定を行います。
ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Create Empty で新しいゲームオブジェクトを作成します。
名前を UIManager に変更して、UIManager スクリプトをドラッグアンドドロップしてアタッチしてください。

 インスペクターを確認し、Text コンポーネントのアサイン情報が提示されていますので、先ほど作成したカレンシーの値を表示するゲームオブジェクトを
ヒエラルキーからドラッグアンドドロップしてアサインしてください。自動的に Text コンポーネントの情報が変数内に代入されます。


ヒエラルキー画像



インスペクター画像


 以上で完成です。


46.GameManager スクリプトを修正し、時間の経過に合わせてカレンシーが加算される機能を実装する

1.GameManager スクリプトを修正する


 ロジックを組み込んでいくための必要な情報が完成しましたので、この手順では、それらの情報を活用してカレンシーの加算処理を実装していきます。

 最初にロジックの流れをスクリプト内にコメントとして書いておきましょう。これは、処理のスタート地点から書き始めていくといいです。
そして処理のゴール地点までコメントを書いたら、今度はゴール地点からコメントを参考にしながらプログラムを書き込んでいきます。

 スタート地点まで処理を書いていくことができれば、処理の実装とコメントの実装の両方が完成出来ます。


GameManager.cs


 スクリプトを修正したらセーブをします。


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


 GameManager スクリプトに新しく UIManager スクリプトをアサインするための変数が追加されています。
忘れずにアサインしてから、ゲームを実行してください。






 ゲームを実行後、ゲームのステートが Play に切り替わってから、ゲーム内の時間の経過に合わせてカレンシーが加算されていけば成功です。
また、UI の表示が更新されれば制御成功です。

 デバッグを行う際には、インスペクターで情報を確認しながらチェックしましょう。
ステートもカレンシーも確認することができます。


<実装動画>
動画ファイルへのリンク



 またゲームのステートが Play であるときだけカレンシー用の時間の計測が行われるため、
キャラ配置用のポップアップを開いた時にはこの計測が終了し、ポップアップを開いている間はカレンシーの値が加算されなくなります。


<実装動画>
動画ファイルへのリンク


 カレンシーが増えるまでの時間や1回辺りの加算値は GameData スクリプトから設定ができますので、適宜調整をおこなってください。
現在は一度ポップアップを開いてしまうと、ポップアップを閉じてもカレンシーの計測は開始されません。これは次の手順で修正を行います。



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

 次は 手順28 −カレンシーを活用したコスト支払い機能の実装− です。