ゲームにおける動作的な部分は大体出来上がったので、スコアやライフなどのステータスを表示するようにします。いつものようにuGUIの機能を使って進めていきます。
これまでもuGUI機能を使ってきましたが、使い方以外の説明をあまりしていないので、今回は掘り下げながら作業を進めていきたいと思います。
uGUIを使ってステータスの表示を行おう
Canvasを作成する
uGUIのコンポーネントは、Canvasオブジェクト上に配置します。というわけで、まずはシーンビューにCanvasオブジェクトを作成します。
ヒエラルキーウィンドウにCanvasとEventSystemが生成されます。EventSystemは、Canvasオブジェクトの中にあるボタンをクリックする場合などに発生するイベントを受け渡すためのものです。
Canvasをクリックすると、大きな枠のようなものがシーンビューで確認出来ます。
この範囲が実際のゲームにおけるスクリーン上に表示される領域です。オブジェクトをピクセル単位で扱うので、シーンビューで見ると大きく表示されるようになります。
アスペクト比を変更する
スマホ向けのゲームであるためアスペクト比を「16:9」にしておきます。
アスペクト比を変更すると、Canvasのアスペクト比も変更されるようになります。
スコアとライフ用Textオブジェクトの作成
ユニティちゃんの走行距離を得点としたいので、スコアとライフのテキストを作ります。
テキストを作成すると分かりますが「Rect Transform」と「Canvas Renderer」というコンポーネントが付いていると思います。
Rect TransformがCanvas上にあるオブジェクトの位置を管理して、Canvas RendererがUIオブジェクトを描画する役割となっています。
普段から編集しているTextコンポーネントはその名の通り、文字の表示に関する制御を行います。
テキストを2つ作成したらそれぞれ名前を「ScoreText」「LifeText」に変更します。
それぞれのテキストを編集します。シーンビューにある「2D」ボタンをクリックするとCanvasが平面に見えるようになるので、UIの編集がしやすいと思います。
基本的に2Dゲームを作る際に使用するモードなので、3Dオブジェクトを編集する場合は3Dモードで行うようにしてください。
スコアを左上に、ライフを右上に配置します。それぞれのテキストが何を表しているのか分かるような文字を入力しましょう。
アンカーの設定について
テキストを上の方に移動させましたが、オブジェクトの位置はCanvasの中央からの距離で管理されているので、端末によっては意図いない位置にテキストが表示されてしまいます。
こういったアスペクト比の対策としてアンカーを使用しましょう。
アンカーは、UIオブジェクトの位置の基準を、Canvasの指定した位置に変更することが出来ます。
基準を左上にしておけば、どのような端末でも指定した場所から同じ距離の位置にUIを表示させることが出来るようになります。
先ほど左上に配置したScoreTextの場合は、ScoreTextを選択した状態でインスペクターからアンカーを「top-left」に変えましょう。
これで、左上を基準に位置が設定されました。ゲームビューで画面の幅を変更してテキストが左上に固定されているか確認すると良いと思います。
違う解像度における対応について
続いて、端末によって異なる解像度の対応について行っていきます。
何もしない場合、高解像度の端末でテキストが小さく表示されてしまい、低解像度の端末では逆に大きく表示されてしまいます。
この問題を解決するには「Canvas Scaler」コンポーネントを使うようにします。
Canvas Scalerは、基準となる解像度から比率を調整するように、Canvasのスケールを自動で変更してくれる機能です。
まずは、Canvasを選択してUI Scale Modeを「Scale With Screen Size」に変更します。
Reference Resolutionは、基準となる解像度を入力します、先ほどアスペクト比を「16:9」に設定しているのでこのアスペクト比に対応した解像度を指定します。
Screen Match Modeは「Expand」にします。Expandは基準となる解像度よりも比率が大きくなった際にCanvasの領域を広げます。
設定を変更してゲームビューを見るとテキストの大きさが変わっていると思うので、Font Sizeなど再設定しましょう。
ライフを表示させる
ユニティちゃんは敵に2回当たるとゲームオーバーなので、ライフ用の赤いバーの画像をペイントで軽く自作しました。ライフと分かるような素材をユニティちゃんのライフの数だけ用意しましょう。
画像をインポートしたら、画像を選択してTexture TypeをSprite(2D and UI)に変更してApplyをクリックします。
Imageを作成したら「life1」等と名前を変更してSource Imageに画像を設定します。
ライフとテキストで表示している右のほうに配置しました。ちなみに、ライフゲージは一般的に横長のイメージがあるのでWidthを「120」としてHeightを「70」にしています。
ゲームビューで見た時にライフゲージ同士が繋がっているように配置するのがポイントです。
それぞれにアンカーの設定を行っても良いんですけど、ライフの数が多い場合は面倒ですね。
というわけで今回は、`Panelを使って複数の画像をまとめて管理しましょう。
パネルを作成したらアンカーを「right-top」に変更します。Rectツールを使って半透明の領域を小さくして、ライフゲージは収まるようにします。
それぞれのライフをパネルオブジェクトの子に設定します。これでアンカーの基準がパネルのRectTransformに変わります。
半透明の部分は不要なので、パネルにアタッチされているImageコンポーネントのチェックを外しましょう。
こういった複数のオブジェクトをまとめる機能がRect Transformの役割になります。
UIの更新を行うスクリプトを作成する
ダメージを受けた時にライフゲージを減らす処理と、ユニティちゃんが進んだ距離をスコアとしてテキストに反映させる処理をスクリプトにしていきます。
新規スクリプト「Status」を作成します。
ユニティちゃんのライフをチェックして、登録しておいたライフゲージの非表示でライフを減らすようにしています。
スコアは、ユニティちゃんの走行距離をそのまま得点としました。
続いてUnitychanControllerスクリプトにライフの値を取得するメソッドを追加します。
これでエラーは解消されるはずです。
空のゲームオブジェクトを作成してStatusスクリプトをアタッチしましょう。
各プロパティにそれぞれのオブジェクトを設定します。ライフゲージは右から先に非表示にしたいので2個ある内の右に配置しておいた「life2」をElement 0に対応させています。
ゲームを実行して、点数とライフの減少について確認しましょう。
これでランニングゲームは一通り完成です。後はタイトルシーンを作ったり、ボタンを配置してボタンで操作できるようにすると良いとおもいます。
アイテムを作ったり、進んだ距離に応じてステージに出現する敵の数を増やしたり、いくらでも面白くすることが出来るので、試行錯誤してみてください。