【Unity】TextMesh Proで数字をスプライト表示する

こじゃらこじゃら

ゲーム画面のスコア時間などの数字を画像で表示する方法はないの?

このはこのは

やり方はいくつかあるけど、TextMesh Proを使えば手軽だわ。

TextMesh Proで数字をスプライト画像として表示する方法の解説記事です。

これは、TextMesh Proのスプライトアセット機能を用いることで実現できます。

参考:Sprites, TextMesh Pro Documentation

数値を指定するスクリプト側では、次のコードのように文字列形式に変換してTextMeshProUGUIコンポーネントに指定する形となります。

// TextMesh ProのUIテキスト
TextMeshProUGUI text;
// 表示する数値
int value = 1234;

・・・(中略)・・・

// TextMesh Proのテキストに値を反映
text.text = value.ToString();

// GC.Allocを発生させずに指定することも可能
text.SetText("{0}", value);

上記を実現するためには、スプライトフォントの作成とTextMesh Pro側の設定が必要になりますが、これらの工程はノーコーディングで行えます。

本記事では、TextMesh Proとスプライトフォントを用いて数字をスプライト表示する方法について解説していきます。

動作環境
  • Unity 2022.1.11f1
  • TextMeshPro 3.0.6
  • 2D Sprite 1.0.0

スポンサーリンク

スプライトの準備

まず、表示させたい数字の画像ファイルを用意します。

一つの画像ファイルにまとめられている必要があります。

例では、0~9の数字とマイナス記号の文字が並んだ画像としました。

必要パッケージのインストール

TextMesh Proを使用するためには、TextMeshProパッケージがインストールされている必要があります。

また、用意したスプライト画像をマルチスプライトとして扱えるようにするために2D Spriteパッケージをインストールする必要があります。

これらのパッケージは、以下の手順でインストールします。

パッケージのインストール手順
  • トップメニューのWindow > Package Managerを選択し、Package Managerウィンドウを開く
  • 左上のPackage: ~ボタンからUnity Registryを選択
  • 左のリストから該当パッケージ名を選択し、右下のInstallボタンをクリック

最終的に以下のように該当パッケージにチェックマークが付いていればインストール完了です。

注意

これらのパッケージのインストールを忘れると、この後の手順を実施できなくなりますのでご注意ください。

スプライトの導入

予め作成しておいた数字の画像ファイルをUnityエディタのプロジェクトウィンドウにドラッグ&ドロップしてインポートします。

対象のスプライトを選択し、インスペクターよりSprite ModeMultipleに設定、Sprite Editorボタンをクリック、 ポップアップのApplyボタンをクリックし、Sprite Editorウィンドウを開きます。

動画のように、左上のSliceアイコンから自動的にスライスさせると、トリミング作業をある程度自動化できます。

必要に応じて、個別にスライスの領域を調整してください。

最終的に、以下のように1文字ずつマルチスプライト化されていればOKです。

注意

スライスの領域の高さは揃えておくことをお勧めします。異なる高さにすると、不均一なスケールで表示されることがあるためです。

TMP Essential Resourcesの追加

既にTextMesh Proを導入して使えるようになっている環境なら、本手順は不要のためスキップして問題ありません。

トップメニューよりWindow > TextMeshPro > Import TMP Essential Resourcesの順に選択し、パッケージファイルをすべてインポートします。

すると、Assetsフォルダ直下にTextMesh Proフォルダが追加されます。

スプライトフォントの作成

該当の数字スプライトを右クリックし、Create > TextMeshPro > Sprite Assetの順に選択します。

すると、以下のようにスプライトフォントが適用された状態でTextMesh Pro用のスプライトアセットが作成されます。

例のように意図しない順序になる場合があることにご注意ください。

Tips

Sprite Character Tableの文字を選択すると、以下のボタンから順序を変更できます。必要に応じて順序を修正しておくと良いでしょう。

また、必要に応じてEdit Glyphボタンよりスプライトフォントの表示位置などを調整しておきます。

本記事では、文字の左端を基準として揃えて表示するため、BXの値をすべて0に設定するものとします。

注意

デフォルト値では文字の中心を基準として整列されて表示されるようになっています。この状態では文字幅を考慮した整列時に不都合が生じることがあります。そのため、特別な理由がない限りBXを0に設定しておくことをお勧めします。

TextMesh Proのテキスト設定

表示対象のTextMesh Proにスプライトフォントを適用していきます。

例では、Canvasの中央にTextMesh Proのテキストを表示するものとします。

該当するTextMesh ProコンポーネントSprite Asset項目に、先ほど作成した数字スプライトアセットを指定します。

これで、最低限スプライトフォントを表示できるようになりました。

数字のスプライトフォントは、以下のようなリッチテキスト形式のspriteタグを文字列として指定すれば表示されるようになります。

「1234」のような数字文字列として指定する方法は後述します。

<sprite=0><sprite=1><sprite=2><sprite=3><sprite=4>

参考:Rich Text, TextMesh Pro Documentation

Tips

縦方向の位置が意図しない位置ずれている場合は、スプライトアセット側の表示位置BYを調整するか、Alignment項目をBaselineやMidline等に設定すると解消される場合があります。

文字列指定でスプライト表示可能にする

spriteタグを使えば数字を表示できますが、例えば「1234」のような文字列として指定したい場合、前述の設定のままではフォント側の数字が優先されてしまい、スプライト表示になりません。

この問題は、フォント側に数字の文字を含めないようにし、数字の場合はスプライトアセット側にフォールバックさせるようにすれば回避可能です。

フォールバックの例

設定手順は次のようになります。

文字コードの設定

スプライトアセットの各スプライト文字に該当する数字の文字コードを対応させます。

スプライトアセットSprite Character Tableの各要素のUnicode欄に以下のような文字コード(Unicode、16進数)を指定します。

文字文字コード(16進数)
030
131
232
333
434
535
636
737
838
939
2D
文字コード一覧

参考:Unicode 15.1 Character Code Charts

Unicode欄に設定するときは、要素をクリックして文字コードを入力した後、何度か要素をクリックしないと設定が反映されないことがあるようです。

最終的に以下のように文字コードが設定されていればOKです。

数字が含まれないフォントの作成

数字をスプライトアセットにフォールバックさせるために、数字が含まれないフォントを作成します。

例では、空フォントを作成するものとします。

まず、トップメニューよりWindow > TextMeshPro > Font Asset Creatorの順に選択し、Font Asset Creatorウィンドウを開きます。

次に、Font Asset CreatorウィンドウのSource Font File項目適当なフォントを指定します。空フォントの場合、解像度は無視してよいため、Atlas Resolutionを両方とも8(最低解像度)に変更しておきます。

また、Character Set項目Custom Charactersを設定し、Custom Character Listに数字を含めないようにします。例では空フォントのため、未入力の状態にします。

設定を終えたら、Generate Font Atlasボタン > Saveボタンの順にクリックし、フォントアセットを作成します。

フォントの適用

上記で作成したフォントを対象のTextMesh ProテキストFont Asset項目に指定します。

これで、テキスト欄に数字を入力すると、スプライトアセット側の数字が適用されるようになります。

スクリプトからの設定例

スクリプトから値などを設定したい場合は、TextMeshProUGUIコンポーネントtextプロパティに文字列変換された値を指定する流れとなります。

参考:Class TextMeshProUGUI | TextMeshPro | 3.0.9

以下、指定された値をTextMesh Proのテキストに反映するサンプルです。

SetNumberExample.cs
using TMPro;
using UnityEngine;

public class SetNumberExample : MonoBehaviour
{
    // TextMesh ProのUIテキスト
    [SerializeField] private TextMeshProUGUI _text;

    // 表示する数値
    [SerializeField] private int _value;

    // 数値のプロパティ
    public int Value
    {
        get => _value;
        set
        {
            _value = value;
            OnUpdateValue(value);
        }
    }

    // 表示する数値の更新
    private void OnUpdateValue(int value)
    {
        if (_text == null) return;

        _text.text = value.ToString();
    }

#if UNITY_EDITOR
    // インスペクター等から編集されたときに表示更新(エディタ専用)
    private void OnValidate()
    {
        OnUpdateValue(_value);
    }
#endif
}

上記をSetNumberExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチし、インスペクターよりText項目にTextMesh Proのテキスト、Value項目に表示したい値を指定すれば機能するようになります。

GC.Allocを発生させないようにする

先述のサンプルスクリプトでは、数値をToStringメソッドで文字列オブジェクトに変換していたため、テキストを更新するたびにGC.Allocが発生してしまいます。

TextMeshProUGUI.SetTextメソッドを用いると、この問題を回避できます。

参考:TextMesh Pro Documentation:

以下、メモリの確保をさせずに表示更新できるようにした例です。

SetNumberNonAllocExample.cs
using TMPro;
using UnityEngine;

public class SetNumberNonAllocExample : MonoBehaviour
{
    // TextMesh ProのUIテキスト
    [SerializeField] private TextMeshProUGUI _text;

    // 表示する数値
    [SerializeField] private int _value;

    // 数値のプロパティ
    public int Value
    {
        get => _value;
        set
        {
            _value = value;
            OnUpdateValue(value);
        }
    }

    // 表示する数値の更新
    private void OnUpdateValue(int value)
    {
        if (_text == null) return;

        // GC.Allocを発生させずに数値を指定可能
        // ただし、UnityEditor上ではGC.Allocが発生することに注意
        _text.SetText("{0}", value);
    }

#if UNITY_EDITOR
    // インスペクター等から編集されたときに表示更新(エディタ専用)
    private void OnValidate()
    {
        OnUpdateValue(_value);
    }
#endif
}

使い方は先のサンプルスクリプトと一緒です。実行結果も同様のため割愛させていただきます。

変更箇所は以下部分です。

// GC.Allocを発生させずに数値を指定可能
// ただし、UnityEditor上ではGC.Allocが発生することに注意
_text.SetText("{0}", value);

数値の指定はstring.Formatメソッドのような要領で可能です。

注意点として、SetTextメソッドはUnityEditor上では必ずGC.Allocが発生する点にご注意ください。ビルド時ではGC.Allocが発生しません。

さいごに

TextMesh Proとスプライトフォントを用いて、数字をスプライト表示する方法を紹介しました。

文字列をスプライト表示するためには、数字が含まれないフォントを作成する必要があったりと少し面倒ですが、実現可能です。

スプライトフォントの機能自体は様々な文字に対応可能なため、絵文字などの埋め込みにも対応できる便利な機能です。

一つの方法として参考にしていただければ幸いです。

参考サイト

スポンサーリンク