ゲーム制作   Unity ソフトウエア 

Unity ソフトウエアでゲーム制作#1モグラたたき編(19.TextMeshPro)

キャッチ画像モグラたたきTextMeshPro

本投稿は2024年9月時点の内容になります。アップデートにより変更となる場合があります。また環境によって違いがあると思いますのであくまで参考として、ご了承ください。

様々な書籍、ブログや動画を参考にさせていただきました。多すぎて一つ一つはtお紹介できませんが感謝です。

初心者の自分がUnity ソフトウエアでゲームを作ってみました。とりあえずシンプルなものということでモグラたたきに挑戦です。ゲーム作ってみるかという感じになったときに、いいタイミングで某ゲームのイベントシナリオ内ミニゲームにモグラたたきが実装されていたのでUIとかエフェクトとか、諸々の仕様をぱくって参考にして作ってみましたよ。様々なHowToの中の選択肢のひとつとして、同じ初心者さんの参考になればよいです。

\ チェック /

TextMeshProを使ってみよう

UIを実装していきます。今回はTextMeshProを使っていこうと思います。

前回の「18.TextMeshPro準備編」と前々回の「17.uGUI Canvas設定」もチェックしてみてください。

\ 前回のTextMeshPro準備編です /

本記事のポイント

  • スクリプトでTextMeshProに値を表示させる方法を解説
  • TextMeshProでアウトラインなどをつける時の注意点(TextMeshProでアウトラインが他のテキストにも影響してしまう問題)

TextMeshProの実装

経過時間を表示するタイマーをTextMeshProを使って実装してみます

TextMeshProによるタイマーの実装例(その1オブジェクトの設置)

  1. ヒエラルキー上で、前々回に作ったCanvas「UI」に「TextMeshPro」を作成。「UI」の上で右クリック>「UI」>「テキスト-TextMeshPro」をクリック 作成された「Text(TMP)」に任意の名前を付けます。今回は「TimerUI」としました。
  2. インスペクターの「TextMeshPro」コンポーネントにプロパティ「NewText」となってる欄をわかりやすい文字に変更します。今回はタイマーなので「00:00」としました。
  3. 「MainSetting」で「FontAsset」を前回準備した「SilkscreenFontNormal」を選択して使ってみます。
  4. 以下その他の設定は任意で。
  5. 今回は「FontSize」を「64」
  6. 「Alignment」を「Center,Middle」、「SpacingOption」の「Character」を「-10」にしてみました。
  7. 「RectTransform」コンポーネントの設定でテキストに合わせて幅を「180」高さ「50」にしました。
  8. 「RectTransform」の「アンカープリセット」(四角にターゲットみたいなってるところ)をクリックして「Shift+Alt」を押しながら「Right,Top」をクリック。テキストが右上に移動したと思います。
  9. これは親の基点(Anchor)を右上であるテキストのオブジェクトの基点(Pivot)も右上に設定して、基点に移動する、の3つの動作をあわせた操作になります。
  10. 「RectTransform」の「位置X」を「-160」、「位置Y」を「-50」に設定しました。

TextMeshProのテキストをスクリプトから表示していきます。

TextMeshProによるタイマーの実装例(その2スクリプト)

  1. 今後のスクリプトの整理のために「Scripts」フォルダーの中に「UI」フォルダーを新規作成します。
  2. そのフォルダー内にスクリプト「TimerUI」を新規作成して「TimerUI」オブジェクトにコンポーネントとしてアタッチします。
  3. スクリプトは以下のように
class TimerUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//UIとTextMeshProを使うためのnamespace
using TMPro;
//TimeSpanを使うためのnamespace
using System;

public class TimerUI : MonoBehaviour
{
    //TextMeshProを使うためのクラス
    [SerializeField] TextMeshProUGUI timerUITMP;

    public void UpdateTimer(float seconds)
    {
        //TextMeshProのフィールドtextに表示したい値を代入秒表示をmm:ss表示に変換
        timerUITMP.text = TimeSpan.FromSeconds(seconds).ToString(@"mm\:ss");
    }

    // Update is called once per frame
    void Update()
    {
        //GameManagerのPlayTimeプロパティ
        UpdateTimer(GameManager.Instance.PlayTime);
    }
}

スクリプトざっくり解説

  • (6)初心者のハマりポイント 重要!「using TMPro」は TextMeshProを使うためのnamespaceの宣言 無いとエラーが出ます! 
  • (8)TimeSpanを使うためのnamespace
  • (13)TextMeshProを使うためのフィールドtimerUIText
  • (15-19)秒を mm:ss 表記にしてにtimerUIText.textで表示する
  • (25)PlayTimeをGameManagerのプロパティからUpdateTimerに渡す
  • インスペクターの「TimerUIText」「TimerUI」オブジェクトをドラッグしてアサインします。

ゲーム再生するとタイマーとして時間が表示されると思います。

次はプレイヤーのレベルを表示するUIを実装します

TextMeshProによるプレイヤーレベルUIの実装例(その1オブジェクトの設置)

  1. Canvas「UI」の子として「空のオブジェクトを作成」名前を「PlayerLevelUI」とします。
  2. アンカープリセットでAnchorとPivotを「Top,Left」に設定します。
  3. 「位置X」を「100」、「位置Y」を「-50」、「幅」を「200」、高さを「50」にします。
  4. 「PlayerLevelUI」の子として「テキスト-TextMeshPro」を2つ作成します。
  5. 1つを名前「PlayerLevelUILabel」にしました。
  6. アンカープリセットでAnchorとPivotを「Left,Middle」に設定します。
  7. 「位置X」を「0」、「位置Y」を「0」、「幅」を「200」、高さを「50」にしました。
  8. 「FontAsset」「SilkscreenFontBold」
  9. 「FontSize」を「64」、「Alignment」を「Left,Middle」文字欄に「Lv.」としました。
  10. もう1つは名前「PlayerLevelUINumeral」にしました。
  11. アンカープリセットでAnchorとPivotを「Right,Middle」に設定します。
  12. 「位置X」を「0」、「位置Y」を「0」、「幅」を「200」、高さを「50」にします。
  13. 「FontAsset」「SilkscreenFontNormal」
  14. 「FontSize」を「72」、「FontStyle」を「Bold」、「Alignment」を「Right,Middle」、文字欄には任意に数字を入れておきます。
  15. 配置などは任意です。今回はテキストをラベルと数字に分けましたが、一緒にしてスクリプト側で書いてもOK

TextMeshProによるプレイヤーレベルUIの実装(その2スクリプト)

  1. スクリプト「PlayerLevelUI」を新規作成して「PlayerLevelUI」オブジェクトにコンポーネントとしてアタッチします。
  2. スクリプトは以下のように
class PlayerStatus
public class PlayerStatus : UnitStatus
{
    //追加のフィールド
    //スコア
    public int Score { get; set; }
    //レベルアップに必要な経験値
    public int RequiredExp {  get; set; }
    //次のレベル獲得経験値
    public int NextExp {  get; private set; }


    //コンストラクタ
    public PlayerStatus(string name, int atk, int def, int level, int maxHp, int exp, UnitType unitType)
    : base(name, atk, def, level, maxHp, exp, unitType)
    {
        Score = 0;
        NextExp = 5;
    }

    //Playerスコアにscore分加算
    public void UpdateScore(int score)
    {
        Score += score;
    }
    
    //経験値更新 今回はモグラたたきなのでプレイ時間を経験値にしてレベルが上がると敵の速度が上がるようしたい
    public void UpdateExp()
    {
        Exp = GameManager.Instance.PlayTime;
    }

    //次のレベル獲得経験値をセット
    public void SetNextExp()
    {
        NextExp += RequiredExp;
    }

    //レベルの更新
    public void UpdateLevel()
    {
        if (Exp > NextExp)
        {
            //経験値がレベルアップのポイントに達したらレベルアップ
            Level += 1;
            SetNextExp();
        }
    }
}

スクリプトざっくり解説 PlayerStatusクラス側

  • (24-27)経験値獲得のメソッド。今回はモグラたたきなのでプレイ時間をそのまま経験値にしています。
  • (30-34)次のレベルアップに必要な経験値を設定
  • (37-45)レベルの更新と次の経験値を設定
class Player
public class Player : MonoBehaviour
{
  //省略
  
    // Update is called once per frame
    void Update()
    {
        //経験値とレベルの更新
        PlayerStatus.UpdateExp();
        PlayerStatus.UpdateLevel();
    }
    
  //省略  
}

スクリプトざっくり解説 Playerクラス側

  • (6-11)経験値とレベルをアップデート
class PlayerLevelUI
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//UIとTextMeshProを使うためのnamespace
using TMPro;



public class PlayerLevelUI : MonoBehaviour
{
    //TextMeshProを使うためのクラス
    [SerializeField] TextMeshProUGUI PlayerLevelTMPNumeral;
    [SerializeField] Player Player;
    
    int currentLevel;

    //初期化
    public void InitPlayerLevelUI()
    {
        //初期化時点のレベルを表示
        currentLevel=Player.PlayerStatus.Level;
        PlayerLevelTMPNumeral.text = currentLevel.ToString();
    }
    //プレイヤーがレベルアップした時に更新して表示
    public void UpdatePlayerLevelUI()
    {
        if(currentLevel < Player.PlayerStatus.Level)
        {
            currentLevel = Player.PlayerStatus.Level;
            PlayerLevelTMPNumeral.text = currentLevel.ToString();
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        InitPlayerLevelUI();
    }
    // Update is called once per frame
    void Update()
    {
        UpdatePlayerLevelUI();
    }
}

スクリプトざっくり解説

  • (7)重要「TMPro」は TextMeshProを使うためのnamespace
  • (20-25)レベル表示の初期化。スタート時点のレベルを表記
  • (27-34)レベル表記の更新

さらにスコア表示するUIを実装します

TextMeshProによるスコア表示の実装例(その1オブジェクトの設置)

  1. Canvas「UI」に「TextMeshPro」を作成。名前は「ScoreUI」としました。
  2. 「RectTransform」高さを「60」にしました。
  3. アンカープリセットでAnchorとPivotを「Top,Strech」に設定します。「位置Y」「-50」に設定しました。
  4. インスペクターの「TextMeshPro」コンポーネントにプロパティ「NewText」となってる欄をわかりやすい文字に変更します。今回はスコアなので「150000」としました。
  5. 「MainSetting」で「FontAsset」を前回準備した「SilkscreenFontNormal」を選択して使ってみます。
  6. 今回は「FontSize」を「80」、「FontStyle」を「Bold」
  7. 「Alignment」を「Center,Middle」にしてみました。
  8. 「SpacingOption」の「Character」を「-10」のして詰めてました。
  9. グラデーションをかけたいので、「ColorGradient」をチェック
  10. 「ColorMode」「VerticalGradient」 「Colors」は上「#EC1200FF」下「#FFA200FF」にしました。まあこの辺はお好みで。
  11. 見づらいのでもうすこし太くして輪郭線を付けるため下の方「Material」を設定します。
  12. 今回はの「Face」の「Dilated」を「0.1」に、「Outline」の「Color」を「84,3,0,255」、「Thickness」を「0.15」にしました。

TextMeshProによるよるスコア表示の実装(その2スクリプト)

  1. スクリプト「ScoreUI」を新規作成して「ScoreUI」オブジェクトにコンポーネントとしてアタッチします。
  2. スクリプトは以下のように
class ScoreUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//
using TMPro;

public class ScoreUI : MonoBehaviour
{    //TextMeshProを使うためのクラス
    [SerializeField] TextMeshProUGUI ScoreTMP;
    [SerializeField] Player Player;

    int currentScore;

    //初期化
    public void InitScoreUI()
    {
        //初期化時点のスコアを表示
        currentScore = Player.PlayerStatus.Score;
        ScoreTMP.text = currentScore.ToString();

    }
    //プレイヤーがあらたなスコアを獲得した時に更新して表示
    public void UpdateScoreUI()
    {
        if (currentScore < Player.PlayerStatus.Score)
        {
            currentScore = Player.PlayerStatus.Score;
            ScoreTMP.text = currentScore.ToString();
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        InitScoreUI();
    }
    // Update is called once per frame
    void Update()
    {
        UpdateScoreUI();
    }
}

スクリプトざっくり解説

  • レベル表示の時と同じ流れなので特に説明する必要はないかと思います。

ゲーム再生してUnitychanをクリックしてみます。得点表示が加算されていくと思います。実装できました。

ここでゲーム画面をよく見てみます。おそらく問題が発生していると思います。同じフォントを使ったタイマーとレベルの数字にもアウトラインがついてしまっているはずです。

TextMeshProでアウトラインが他のテキストにも影響してしまう問題

TextMeshProのFaceやOutlineなどは「Material」というオブジェクトの「質感」をあらわすための機能に依っています。TextMeshProではプロパティの「MaterialPreset」で選択したものになります。なので同じ「MaterialPreset」を選んでいるものは同じ質感になってしまうのです。これが「TextMeshProでアウトラインが他のテキストにも影響してしまう」理由です。

TextMeshProで「Material」のOutlineなどを変更するときは注意が必要

  • 同じ「MaterialPreset」を選んでいると同じ質感になってしまうので注意(意図的に同じにしたいときはOK)

解決策もいたってシンプルです。別の「MaterialPreset」を用意すればいい。

TextMeshProでOutlineなどが他のテキストに影響して困ったときは別の「MaterialPreset」にする

  • 新しい「MaterialPreset」を作って、それを使えばいい。

以下方法です。

TextMeshProの「MaterialPreset」を新たに作って変更する方法

  1. 今使っている「MaterialPreset」はデフォルトなので一旦もとに戻します(「Face」の「Dilated」を「0」に、「Outline」の「Color」を「0,0,0,255」、「Thickness」を「0」に戻します)。
  2. まずはデフォルトの「MaterialPreset」をインスペクター上に表示します
  3. フォントアセットの保存先を開きます(「TextMeshPro」>「Resources」>「Fonts&Materials」)
  4. 対象のフォント(SilkscreenFontNormal)の「▶」をクリックして展開します。
  5. マテリアル(SilkscreenFontNormalSDF Material)を選択。インスペクター上に表示されたと思います。
  6. インスペクターのマテリアルの名前の横の点3つ(錠マークの横ではなく、その下)をクリック
  7. メニューから「CreateMaterialPreset」をクリック
  8. 新しくMaterialPresetが作成されました。わかりやすいようにプロジェクト上で名前を変更します(今回は名前の後ろに「_Score」を追加)。
  9. 「ScoreUI」の「MaterialPreset」で今回作ったものを選択した後、Outlineなどを変更します。
  10. 今回はの「Face」の「Dilated」を「0.1」に、「Outline」の「Color」を「84,3,0,255」、「Thickness」を「0.1」にしました。
  11. 今度はスコア表示の部分だけ変更されたと思います。これで解決です。

TextMeshProのRayCastTargetの外し方

最後に今回設置したTextMeshProは表示のみなので、RayCastTargetを外します。外しておかないと気づかないうちに他のボタンの障害になってクリックが反応しなくなるからです。

TextMeshProの「RayCastTarget」をの外し方

  1. TextMeshProの「Setting」から「ExtraSetting」をクリック
  2. RayCastTargetの項目のチェックを外します

まとめ

まとめ

  • TextMeshProのテキストをスクリプトから使うにはnamespace「TMPro」が必要。
  • TextMeshProのテキストをスクリプトから変更するにはTextMeshProUGUIのフィールド「text」を変更する。
  • TextMeshProでアウトラインやグローなど質感を変える時はあらたに「MaterialPreset」を作成して、それを使用するのがおすすめ
  • TextMeshProのRayCastTargetの設定は「ExtraSetting」から変更できる
ユニティちゃん公式ホームページへ
ユニティちゃん公式ホームページ
ユニティちゃんライセンス
ユニティちゃんの画像、素材、ライセンスロゴはユニティちゃんライセンス条項を元に使用しています

\ 初学に使った書籍です /

動画×解説でかんたん理解! Unityゲームプログラミング超入門

大角 茂之/大角 美緒

マケイヌ的おすすめ度

わかりやすい度

提供素材がよくてテンション上がる度

〇おすすめポイント

素材が良くてモチベがあがります。

×よくないポイント

動画解説前提なので図版が小さいのが玉に瑕

おすすめ記事

 

プロフィール

マケイヌ

人生のメインストリームから外れた40代の♂。

90年代オルタナにはまり、文字通りメインストリームから逸脱。 その後もたびたび人生から逃亡。

心が動いた作品の紹介や 自分のちいさな経験、HowToを発信できればと日々模索中。

1年後までにイラストと写真のポートフォリオをつくりたい。

記:2019年12月

▼プロフィールはこちら

Follow me

アーカイヴ