top of page

2Dランゲーム編

Lesson4 UIを作ろう

4-1

4-1 UI用シーンの作成

4-1 UI用シーンの作成

1

UIシーンの作成

 スコアや現在位置を表示するためのUIを作成しましょう。UIのデザインについてはあくまでサンプルなので、みなさんの好みに合わせて調整してください。

 3Dアクションゲーム編ではメインシーンにそのままUIを作成していました。しかし、ステージを複数作成したい場合、この方法では小さな修正でも全てのシーンを修正する必要が出てきてしまいます。

​ 例えば、UIに新しいボタンを1つ追加したい時も、全てのステージをいちいち開いてボタンの追加作業をしなければならないということです。この方法では、ステージが増えるほど作業が大変になってしまいます。

 たくさんのステージを作成してもUIが使いまわせるように、今回はUI用のシーンを作ってメインシーンに合成する手法を取りましょう。

​ これでステージを量産しても、元となっているUIシーンが同じなので修正が簡単にできるようになります。Unityでは簡単に複数のシーンを合成することができます。

 UI用のシーンを作成しましょう。

​ Scenesフォルダ内にUIシーンを作成してください。

2

メインカメラの
​削除

 UI​シーンをダブルクリックして開いてください。
 

​ シーンには標準でメインカメラがありますが、シーンを合成する時にメインカメラが複数あると不具合が起きてしまうので削除しておきましょう。カメラがないためGame内のプレビューは表示されませんが問題ありません。

3

ウィンドウ画像の
​スライス

 まずはスコア表示用のウィンドウを設置しましょう。

 

 ウィンドウを作成するときはSpriteEditorのSlice機能を使うと便利です。

 普通にウィンドウを変形させると左の画像のように四隅が歪んでしまいますが、この機能を使うと右の画像のように四隅の大きさを固定したままウィンドウの大きさを変えることができます。

 ウィンドウ画像をスライスして使う準備をしましょう。

 

 「Sprite」→「UI」→「Main」内のMedium-boxというウィンドウ画像を選択して、SpriteModeを「Multiple」に、MeshTypeを「Full Rect」に変更してください。

 設定を変更したら「Apply」ボタンを押しましょう。

 次はSprite Editorを開いてください。

​ ウィンドウ画像全体を緑のラインで囲むようにドラッグしてください。

 画像全体を囲うと、右下にSpriteという枠が出てきたと思います。

 L、T、R、B 全てに「8」を入力してください。画像が9分割されていたらOKです。この設定をすることで画像を拡大しても四隅の縦横比(アスペクト比)は保たれたままになります。

​ 設定できたら右上の「Apply」を押してSprite Editorを閉じてください。

4

ウィンドウ画像の
​追加

 ヒエラルキーから「UI」→「Image」を選択してください。画像と同時にCanvasやEventSystemも自動で追加されます。

​ ImageのSauce Imageに先ほど設定したmedium-boxをドラッグ&ドロップしてください。

※ 直接シーン上にスプライトをドラッグ&ドロップしてしまうと、スプライトとしてオブジェクトが追加されてしまうので注意!

・Imageの名前をわかりやすいものに変更しておきます(教材ではScoreWindow)

​・座標、幅、大きさを調整して左上にウィンドウを配置してください

​  PosX=-220 PosY=155

  Width=80 Height=30

​  Scale=2

5

キャンバスの
​大きさ調整

 ウィンドウサイズが変わっても大きさを調整できるように、Canvasの設定を変更してください。

 Canvasを選択してUI Scale Modeを「Scale With Screen Size」に変更、Reference Resolutionを適切な値に調整してください。

​(3Dアクションゲーム編の4-4も参考にしましょう)

6

TextMeshProの
​導入

 スコア表示用のテキストを追加しましょう。

 ヒエラルキーから「UI」→「Text - TextMeshPro」を選択して追加しましょう。

​ TextMeshProのインポートをするウィンドウが開くので「Inport TMP Essentials」を選択してください。

7

フォントの導入

 デフォルトのフォントでは雰囲気に合わないので、今回はドットのフリーフォントを使用します。

 以下のURLからフォント素材をダウンロードしてください。

​※ ダウンロードできない場合は適当なドット用フォントを探すか、このパートは飛ばしてください

​【使用するフォント→PixelMplus】https://itouhiro.hatenablog.com/entry/20130602/font

 フォントがダウンロードできたらフォルダを解凍しましょう。

​ フォルダ内の「PixelMplus12-Regular.ttf」をプロジェクト内にドラッグ&ドロップしてください。

 これでフォント素材を追加できましたが、変換しないとTextMeshProで使うことができないので注意しましょう。

 左上の「Window」→「TextMeshPro」→「Font Asset Creator」を選択してください。

 Font Asset Creatorが開いたら、Sauce Font Fileに使用するフォント素材を設定してください。

​ 他のパラメータはそのままで構いませんが、お好みで変更してもOKです。

 Select Font Assetに「LiberationSans SDF」を設定してください。これでUnityで使えるように変換する文字を指定できます。

 このゲームのUIでは日本語を使いませんが、もし日本語を使いたい場合は3Dアクションゲーム編同様このサイトを参考にしてください。

 設定が終わったら「Generate Font Atlas」を選択してください。しばらく待つと変換が完了します(設定によって時間がかかる場合があります)

 変換が終わったら「Save」を押して素材を保存してください

8

​テキストの設定

 それではTextMeshPro側の設定をしていきましょう。

 先ほど追加したTextMeshProオブジェクトの名前をわかりやすいものに変更してください(サンプルではScoreText)

 ScoreTextをScoreWindowの子オブジェクトにしましょう。これによってテキストをウィンドウの中央に調整しやすくなり、またウィンドウが移動するとテキストの方も一緒に動くので演出も作りやすくなります。

 インスペクターでScoreTextの設定をしていきます。

 

・Alignmentを中央揃えに変更して、ウィンドウの中央になるように座標を調整します(PosX、PosY共に0で構いません)

・ここで表示するテキストはダミーなので適当な数字にしておきます

・Font Assetに先ほど変換したフォント素材をドラッグ&ドロップで設定してください

・Font Sizeなどもお好みで調整してください

 サンプルではUnderlayのパラメータを調整して文字に影を落としています(追加するかはお好みで)

9

​バーのスライス

 次はプレイヤーの進行状況を示すバーを作成しましょう。

​ 「Sprite」→「UI」→「Main」内のhealth-bar-boxという画像を選択して、SpriteModeを「Multiple」に、MeshTypeを「Full Rect」に変更してください。

 ウィンドウ画像では画像を9つにスライスしましたが、3つにスライスすることもできます。

 Sprite Editorを開いて、全体を緑のラインで囲うようにドラッグしてください。

​ Spriteウィンドウが開いたら、LとRの値を10にしてください。画像が左右と中央に分割されます。これで画像を拡大しても左右の部分は縦横比が保たれるようになります。

 設定が終わったら右上の「Apply」をクリックしてSprite Editorを閉じてください。

 ヒエラルキーから「UI」→「Image」で新しい画像を追加してください。画像を追加できたらインスペクターから設定をしていきます。

・Imageの名前をわかりやすいものに変更してください(サンプルではBarBox)

・座標と幅を調整してください

  PosX=0 PosY=150

  Width=260 Height=15

・Sauce Imageに「Sprite」→「UI」→「Main」内の「health-bar-box」を設定してください

​・Image Typeが「Sliced」になっていることを確認してください(画像を設定すると自動で変更されるはず)

10

バー本体の追加

 次はバー本体を追加しましょう。

​ ヒエラルキーから「UI」→「Image」で新しい画像を追加してください。追加されたImageにわかりやすい名前をつけておいてください(サンプルではBar)

 BarをBoxBarの子オブジェクトにしてください。

 インスペクターの設定をしましょう。

・幅を調整してください

  Width=242 Height=9

・Sauce Imageに「Sprite」→「UI」→「Main」内の「health-bar」を設定してください

 Image Typeを「Filled」に変更してください。この設定にすると画像を一部分だけ描画することができるようになります。

 Fill Methodでは画像をどのように描画するか設定することができます。Fill Methodを「Horizontal」に変更してください。

​  設定できたらFill Amountのスライダーを操作して、バーが増減しているように見えることを確認してください。

 Fill Amountが1.0の時は画像が100%表示されます。0.5にすると半分、0にすると表示されなくなります。

 後ほどFill Amountの値をスクリプトから操作して、進行度バーを作っていきます。

​ 今回はバーを進行状況を示すものとして作成しましたが、FilledはHPバーなどあらゆるバーに応用することができます。ぜひ自分のゲームにも使ってみてください。

11

アイコンの分割

 Fill Methodを変更することで円形ゲージも簡単に作ることができます。実際に設定を変更して、どのように描画されるか確認してみましょう。

Unity Tips!

 次はユニティちゃんのアイコンを配置しましょう。

 ユニティちゃんのアイコンはアニメーションできるようになっているので​、まずはその設定をしていきます。流れは宝石のアニメーションを作成した時と同じです。

​ 「Sprite」→「UI」→「Main」内の「UniIc1」を選択して、Sprite ModeをMultipleに変更してください。

 設定が終わったらApplyボタンをクリックして、Sprite Editorを開いてください。

 

 左上のSliceボタンをクリックしてください。

 Typeを「Grid By Cell Count」に変更して、Cに2を入力しましょう。画像が左右に分割されます。

​ Sliceボタンをクリックしてから、右上のApplyボタンをクリックしてください。

12

アイコンの追加

 Applyが終わったらSprite Editorを閉じてください。

 ヒエラルキーから「UI」→「Image」を選択して画像オブジェクトを追加してください。

​ 名前はわかりやすい名前で構いません(サンプルではUniIcon)

​ アイコン画像もバーと同じようにBarBoxの子オブジェクトにしてください。

 インスペクターからUniIconのパラメータを調整してください。

・座標と幅を調整してください

  PosX=0 PosY=2.5

  Width=24 Height=24

​・Sauce ImageにUniIc1の画像を設定してください

13

アニメーションの
​作成

 画像のパターンを切り替えるアニメーションを作成しましょう。

​ Animationフォルダ内に「UIAnimation」フォルダを作成してください。

 UIAnimationフォルダ内にアニメーションを作成して、ヒエラルキー内のUniIconオブジェクトにドラッグ&ドロップしてください(サンプルでのアニメーション名はUniIconAnim)

 アニメーションをダブルクリックしてアニメーションウィンドウを開いてください。

​ ヒエラルキー内のUniIconオブジェクトをクリックしてから「Add Property」→「Image」→「Sprite」を選んで項目を追加してください。

 1枚目(赤枠のユニティちゃん)の次のフレームに2枚目(白枠のユニティちゃん)をドラッグ&ドロップしてください。デフォルトで他のキーが配置されていた場合は削除して「1フレーム目に赤枠のユニティちゃん、2フレーム目に白枠のユニティちゃん」だけになるようにしてください

 このままでは画像の切り替わりが早すぎて目に悪そうです。

 単純にアニメーションの速度を変えるだけなら、サンプルレートを調整すると楽に変更できます。サンプルレートは1秒間に打てるキーの数で、値を小さくすることでアニメーションを遅くすることができます。

 

​ アニメーションウィンドウの右端にある3つの点が描かれたボタンをクリックして「Show Sample Rate」を選択してください。

 左側にSamplesというサンプルレートを指定する枠が表示されるので、1を入力してからEnterを押してください。​アニメーション速度が変わったらOKです。

 アニメーションがループ再生する設定になっているか確認しておいてください。

14

スタートとゴール
​アイコンの追加

 最後にスタートとゴールを示すアイコン画像を配置しましょう。特殊な設定は必要なく、単純にオブジェクトを追加するだけです。

 まずはヒエラルキーから「UI」→「Image」を選択して2枚のImageを追加してください。

 今までと同じようにBarBoxの子オブジェクトにしましょう。

 UI画像はヒエラルキー内で下にあるオブジェクトが前面に表示されます。ユニティちゃんのアイコンが前面に表示されるように、順番を並び替えてください。

 インスペクターからそれぞれの画像の設定を行ってください。

​【スタートアイコン】

・座標と幅を調整してください

  PosX=-120 PosY=22

  Width=20 Height=20

​・Sauce Imageに「Sprite」→「UI」→「Main」内の「arrow」を設定してください

【ゴールアイコン】

・座標と幅を調整してください

  PosX=116 PosY=22

  Width=16 Height=20

​・Sauce Imageに「Sprite」→「UI」→「Main」内の「flag」を設定してください

 これでUI画像の仮配置が完了しました。

15

UIシーンの合成

 まだUIの更新処理を実装していませんが、先にStage1シーンにUIシーンを合成してみましょう。

​ GameManagerスクリプトを開いて赤い部分のコードを追加してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

 

public class GameManager : MonoBehaviour
{
    // ゲームの状態
    public enum GameState
    {
        enGameState_Play,           // プレイ中
        enGameState_GameOver,       // ゲームオーバー
        enGameState_Clear,          // ゲームクリア
    }

​~後略~

~前略~

    // スコアを取得
    public int GetScore()
    {
        return Score;
    }


    // Awakeなので注意
    void Awake()
    {
        // UIシーンを合成
        SceneManager.LoadScene("UI", LoadSceneMode.Additive);
    }

 

    void Start()
    {

    }

 

    void Update()
    {

​~後略~

【プログラムの解説】

・3Dアクションゲーム編で解説した通り、スクリプトでシーンを扱う際は最初に

using UnityEngine.SceneManagement; を追加する必要があるので注意しましょう。

・Awake関数はStart関数より先に実行される関数です。

​Start関数には後ほどUI更新処理を書くので、UIシーンのロードはAwake関数に書いています。

・LoadScene関数の第二引数にはLoadSceneModeを指定することができます。

第二引数が未入力の場合はSingle(シーンを上書き)モードになっていますが、Additiveモードを指定することで、シーンを合成することができます

​ 早速確認したいところですが、このまま実行するとエラーが発生してしまいます。

 ビルド対象のシーンにUIシーンを追加してください。3Dアクションゲーム編のLesson5-5を参考にしましょう。

 Scenes In BuildにUIシーンを追加できたら、Stage1シーンに切り替えて実行してみてください(UIシーンを実行しても何も起きません)

​ Stage1シーンに先ほど作成したUIシーンが合成されていたらOKです。

 ヒエラルキーを確認するとStage1シーンにUIシーンがしっかり合成されていることが確認できます。

4-2

4-2 スコアの更新

4-2 スコアの更新

1

​スコア表示の更新

 シーンの合成ができたところで、まずはスコアを更新しましょう。

 3Dアクションゲーム編ではUpdate関数で更新していましたが、今回は軽量化も意識した別の方法でスコアを更新します。

 そもそもUpdate関数というのは毎フレーム実行される関数なので、Update関数内の処理が増えれば増えるほどゲームは重くなります毎フレーム描画を更新するより、スコアの値が変わった瞬間だけ描画を更新した方が無駄な処理を実行しなくて済みます。幸いなことに「スコアの値が変わった瞬間」は既に関数になっているので、これを活用しましょう。

 まずはUI更新用のスクリプトを作成しましょう。

​ 新しいスクリプトUI_Scoreを作成して以下のように入力してください。青い部分は穴埋めです。

​【ヒント】3Dアクションゲーム編のLesson4を参考にしてください!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// ① TextMeshProを扱う時に必要
(ここに入力)

 

public class UI_Score : MonoBehaviour
{
    TextMeshProUGUI m_text;

 

    // Awakeなので注意
    // Awake関数はStart関数より先に実行される

    void Awake()
    {
        // ② 自身にアタッチされているTextMeshProを取得して、m_textに代入
        (ここに入力)
    }

 

    public void ScoreUpdate(int score)
    {
        // 引数を使ってスコアを更新
        m_text.text = "" + score;
    }
    
}

 コードが書けたら保存して、UIシーンのScoreTextオブジェクトにUI_Scoreスクリプトをアタッチしてください(ここからは複数のシーンを編集していくことになるので、今どのシーンを見ているか注意しましょう)

2

タグの追加&設定

 後から検索しやすいようにScoreTextオブジェクトにScoreTextタグを設定してください。タグの追加方法は過去のレッスンを参考にしてください。

3

更新処理の実行

 後はスコア増加のタイミングでScoreUpdate関数を呼ぶだけになります。

 GameManagerスクリプトを開いて赤い部分のコードを追加してください。

~前略~

    [SerializeField, Header("スコア")]
    int Score = 0;
    // スコア用UIを保存
    UI_Score m_uiScore;

 

    // スコアを加算
    public void AddScore(int score)
    {
        Score += score;
        // 現在のスコアを渡してUI更新
        m_uiScore.ScoreUpdate(Score);

    }

    // スコアを取得
    public int GetScore()
    {

​~後略~

~前略~
 

    // Awakeなので注意
    void Awake()
    {
        // UIシーンを合成
        SceneManager.LoadScene("UI", LoadSceneMode.Additive);
    }

 

    void Start()
    {
        // ScoreTextタグからUI_Scoreを取得
        m_uiScore = GameObject.FindGameObjectWithTag("ScoreText").GetComponent<UI_Score>();
        // 初期値に更新
        m_uiScore.ScoreUpdate(Score);

    }

 

    void Update()
    {
        
    }
}

【プログラムの解説】

・オブジェクトの検索は合成したシーンも対象になります。今回はStage1シーンにあるGameManagerコンポーネントがUIシーンにあるScoreTextを検索しています。

 一連の処理ではAwake関数とStart関数の呼ばれる順番の違いを活用しています(よくわからない人は気にしなくてもOKです)

 ここまでコードが書けたら保存して、Stage1シーンを実行してみてください。

 宝石を取得することでUIのスコアが更新されるようになったらOKです。

4-3

1

進行度の計算

 今回のUI更新の方法よりステップアップした処理として、デリゲート(イベント)を用いる方法があります。さらにUniRxというライブラリを用いることで、より高度なイベント処理や非同期処理を行うことができます。

 ここでは解説を省きますが、より大規模なゲームを作るときには学習しておくと良いでしょう。

​【参考サイト】Unity(C#)でのデリゲート/イベントのつかいかた

Unity Tips!
4-3 進行度バーの更新

4-3 進行度バーの更新

 次は今どこまで進んでいるかを示すバーを更新できるようにしましょう。

​ このバーを実装するために必要な座標は「スタート地点」「ゴール地点」「現在地点」の3つです。スタート地点とゴール地点の座標を元に、現在地点がステージの何%の場所なのかを計算してみましょう。

 スコアと違ってこちらは常に変化するので、Update関数で更新しましょう。

 UI_Progressスクリプトを追加して、以下のように入力してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;   // UIを扱う時に必要

 

public class UI_Progress : MonoBehaviour
{
    [SerializeField]
    Image BarImage;
    [SerializeField]
    GameObject UniIcon;
    [SerializeField]
    Vector3 BarStartPos, BarEndPos;

 

    // 進行度計算に必要な情報
    Vector3 m_startPos;     // スタート位置
    Vector3 m_goalPos;      // ゴール位置
    GameObject m_player;    // 現在位置

 

    // スタートからゴールまでの距離(X)
    float m_range = 0.0f;

 

    void Start()
    {
        // プレイヤーを検索
        m_player = GameObject.FindGameObjectWithTag("Player");
        // スタート位置を取得
        m_startPos = m_player.transform.position;
        // ゴール位置を取得
        m_goalPos = GameObject.FindGameObjectWithTag("Goal").transform.position;

 

        // スタートからゴールまでの距離を計算
        m_range = m_goalPos.x - m_startPos.x;
    }

 

    void Update()
    {
        // プレイヤーがいないなら中断する
        if (m_player == null)
        {
            return;
        }

 

        // 進行度の計算
        float r = m_player.transform.position.x - m_startPos.x;
        float fill = r / m_range;

 

        // バーの更新
        BarImage.fillAmount = fill;

        // アイコンの更新
        Vector3 pos = Vector3.Lerp(BarStartPos, BarEndPos, fill);
        pos.z = 0.0f;
        UniIcon.transform.localPosition = pos;
    }

}

2

パラメータの設定

【プログラムの解説】

​・ImageコンポーネントのfillAmount に0.0~1.0の範囲の値を入れることでバーの長さを変化させることができます。0.0では全く表示されず、0.5では半分、1.0でバー全体が表示されます。

​・Leap関数は今まで何度か使用していますが、第一引数の座標と第二引数の座標の間を第三引数で補完してくれる関数です。第三引数が0.5だと、第一引数と第二引数のちょうど中間の座標を返します。

 バーの一番左の座標と一番右の座標を使って、アイコンの位置を補完しています。

​ コードが書けたら保存して、UIシーンのBarBoxオブジェクトにアタッチしてください。

​ インスペクター内にパラメータが表示されているので設定しましょう。

・BarImageにヒエラルキーからBarオブジェクトをドラッグ&ドロップ

・UniIconにヒエラルキーからUniIconオブジェクトをドラッグ&ドロップ

・BarStartPosを設定

  X=-120 Y=0 Z=0

・BarEndPosを設定

​  X=120 Y=0 Z=0

 ここまで設定できたらStage1シーンに切り替えて実行してみてください。

※ Playarタグを検索しているため、UIシーンを起動するとプレイヤーがいないことによるエラーが発生するので注意

 プレイヤーの進行に応じて進行度バーが更新されたらOKです。

 これでUIの実装は完了です。

 意図的に右上のスぺースは開けています。LessonEXのポーズ画面を参考にしてポーズボタンなどを追加してみると良いでしょう。

 次のレッスンではステージ2やステージ3を作成して、ステージセレクトからステージを移動できるようにしましょう。また、ステージのクリア状況を保存してステージ1→ステージ2…と進めるようにもしていきます

まとめ

・UIのImage Typeを「Filled」に設定することで、画像を一部分だけ表示することができる

→HPバーなどを作成する際に便利

​・LoadScene関数の第二引数に LoadSceneMode.Additive を指定することで、現在のシーンに新しいシーンを重ねることができる

評価テスト

評価テスト

河原電子ビジネス専門学校
​ゲームクリエイター科

bottom of page