Fungusの基本的な使い方に関しては第1回の記事で解説しておりますので、まだの方はそちらからお読み下さい。
前回、コレクションを利用し、所持しているアイテムをリストとして管理できるようになりました。次はuGUIと連携するためのコマンドを使い、アイテム欄のUIを作ります。
このページでは画面下端にアイテムを入れるボタンを並べ、クリックするとアイテムの説明文が出る、というものを作ることにします。
#ボタンを配置する
まずはガワから用意してみましょう。Unity全体のメニューから**「GameObject」→「UI」→「Button」を選んでuGUI製のボタンを作ります。
ここでHierarchyビューに注目です。もしすでにステージ(第1回参照)を作っているなら、その中のCanvasというものの下にボタンができると思います。
uGUIではCanvasという下敷きが必ず用意され、その上にボタンなどの部品を置いていくことでUIを作る仕組みになっています。**これらは初期状態ではカメラをどこに動かしても同じ場所に表示されるように設定されているため、UIとして使うことができるのです。そしてすでにCanvasがある場合、uGUIの部品を追加するとそこに勝手に入れてくれるようになっています。
しかし、ステージ用のCanvasにボタンを置くとどうも動かないようです(原因についてはまだ調べています……)ので、独自にCanvasを作ってそこへボタンを配置することにしましょう。「GameObject」→「UI」→「Canvas」で作れます。
独自のCanvasを作り、7つほどボタンを並べました。ボタンにはデフォルトで文章(Text)がついてきます。これをアイテム名の表記に使います。
(ここで、それぞれのボタンのTextの名前が同じになっているはずなので、変えておいた方がよいです。後で混乱のもとになるので……)
#ボタンの表記を変更する
続いて、アイテムを拾ったり手放したりした時に各ボタンの表記を変更します。先ほど、アイテムをコレクションの形で管理することにしましたから、例えば下図のようにボタンにも順に0からの番号を振って、アイテムのコレクションと1対1で対応させる……とすれば上手くいきそうですね。
(「ボタンもコレクション化する」わけではないことに注意して下さい。あくまで便宜上番号を振るというだけです)
さっそく処理を作ってみましょう。新しいブロックを用意し、前回説明したElementコマンドでアイテムコレクション0番目のアイテム名を取り出してみてください。
次はその名前を0番目のボタンにあてがいます。FungusからuGUIのテキストを書き換えるにはUI/Set Textコマンドを使います。
Target Text Object欄に変更したいテキストをあてがい、Text欄にその内容を書きます。今回はボタンの中のTextをTarget Text Objectに指定し、Text欄には先ほどコレクションから取り出したアイテム名を入れます。例の変数を文章に埋め込む表記でもいいのですが、「<Value>」と書かれているところをクリックすると変数のメニューが表示され、選択した変数の中身をそのまま渡せますので、そちらを利用するのもよいでしょう。
コマンド一覧は以下のようになると思います。前回解説したように、そもそもない番号を指定してしまった時のエラーを防ぐ機構も入っています。
同様にして、コレクションの1番のアイテム名を1番のボタンに入れる処理、2番のアイテム名を2番のボタンに入れる処理……を作っていきましょう。この時、エクスプローラ(MacならFinder)でやるのと同様にShiftキー+クリックでコマンドをまとめて選択し、その状態でコピペもできるので活用して下さい。
さて、この一連の処理はアイテム欄に変化がある度に呼ばれないといけません。アイテムを入手したり捨てたりする度にCallでこのブロックを呼ぶようにもできますが、それだと多分どこかで呼ぶのを忘れてしまうので、いっそ常に呼ばれ続ける状態にしてしまいましょう。BlockのExecute On Event欄をMonoBehaviour/Updateに指定すれば、毎フレームこのブロックが呼ばれるようになります。
終わったらゲームを起動し、動作を確認してみましょう。
#ボタンを押した時にイベントを起こす
最後に、アイテムが入っているボタンを押すと説明文が表示されるようにしてみましょう。
まずはやはりガワからです。Unityのメニューの**「GameObject」→「UI」→「Panel」で説明文の土台になるパネルを作ります。
しかしこのままだとゲームを開始していきなりパネルが表示されてしまいますので、初めは隠しておくために、パネルを選択してInspectorビューの左上隅あたりにあるチェックを外しておきます(非アクティブ化)。
続いてパネルの中に「GameObject」→「UI」→「Text」で説明文になるテキストと、「GameObject」→「UI」→「Button」でパネルを閉じるためのボタンも作っておきます。
中身作りに進みます。フローチャートで新しいブロックを作って条件をUI/Button Clickedにします。これは指定されたボタンが押された時に起動する条件で、選択すると出てくるTarget Button欄**にそのボタンを指定します。ここではとりあえず0番目のボタンを指定します。
条件も決まったのでコマンドの組み込みに移ります。まずは先ほど非アクティブ化したパネルをもとに戻し、再び画面に表示させましょう。UI/Set Activeコマンドを使います。
Target Game Object欄にアクティブかどうかを変更したいもの(UIに限らずGameObjectなら全てOK)を指定し、Active State欄でアクティブにするか非アクティブにするかを決めます。ここではチェックを入れておきましょう。
次はパネルの中の説明文を書き換えます。アイテムコレクションの中からボタンと対応する番号のものをElementコマンドで取り出して、その種類に応じてIfコマンドで分岐させ、Set Textコマンドでパネルのテキストに説明文を書き込む……というのでいけるでしょう。
ですがアイテムのボタンはいくつもあり、全てが同じ処理をする必要があるので、上記の処理をそれぞれのボタンのブロックに対してコピペするのでは効率が悪いです(例えば一つアイテムを追加するとなったら全部のブロックを直さないといけませんね)。そこで、アイテムの種類に応じた説明文を書き込むブロックを別途作り、各ボタンからはそれをCallコマンドで呼び出すだけという形にしたいと思います(下図)。
Callコマンドで呼び出すだけ、と書きましたが、実際はボタン側でCallする前にアイテムの種類を変数に入れておく必要があり、Callされた説明文書き込みブロックの側でその変数を参照することになります(Callする際になにかデータを渡すということはできないのでそうするしかないようです)。以下のような感じですね。
上記のようにElementコマンドでボタンに割り振った番号のアイテムをコレクションから取ってくるか、あるいは今回ボタンのTextにアイテム名を指定しているのでそれを使うのもアリでしょう。UI/Get TextコマンドでTextに指定した文章を取得できます。
Target Text Object欄で対象のTextを、String Variable欄で取得した文章を入れる変数を指定します。
いずれにせよボタンの方のブロックはこれでOKですので、今度は説明文を書き込むブロックを作ります。
説明文ブロックではボタンの方でアイテム名を入れた変数(上記のコマンド一覧ではTempStringというのに入れています)に応じて分岐させ、アイテムに応じた文章をSet Textコマンドで説明文パネルのテキストに書き込む、という形で組んでみます。
今回は分岐が何通りにも及ぶのでElse Ifコマンドを使うと良いです。これは名の通りElseとIfが一体になったコマンドで、Ifで指定した条件に当てはまらない時にさらに条件をかませて分岐させるということができます。使い方はIfコマンドに準じます。
実際に組むと以下のようになると思います。
最後に説明文のパネルを閉じるボタンに機能をもたせましょう。新しいブロックを作り、UI/Button Clicked条件を指定してTarget Button欄にパネルを閉じるボタンをあてがいます。Set Activeコマンドを追加して説明文のパネルを非アクティブ化するようにします。
長くなりましたがこれでようやくアイテム欄も完成です。さっそく試してみましょう。
前回はコレクション、今回はuGUIとの連携と、2回にわたってアイテム欄の実装に必要な処理について解説してきました。
今回、特にプログラミングに触れた経験がある方は回りくどいことをしている気が……と思われたかと思います(特にアイテムコレクションの中身をボタンに反映する所とか)。このような時により効率のいいやり方をするには自らプログラムを書き、(現状の)Fungusのコマンドにない処理を追加していく必要があります。それでも全くゼロからゲームを作るよりは簡単なので気負いすぎることはありませんし、今はとりあえず先にゲームを完成させることを目指した方がよいでしょう(既存のコマンドだけで作っているうちに「こんな機能があったらいいのに」というのが出てくるはずなので、それを実装することを目標にプログラミングを学べばよいと思います)。
次回はプレイ時間が長いゲームを作る時のために、セーブ・ロード機能について解説する予定です。