[Unity] FontAssetCreatorの文字セットに指定するテキストを作成する拡張



Nプログラマです。

今回は、UnityのFontAssetCreator機能の補助ツールのような拡張機能を作る内容です。

概要

FontAssetCreatorのCharacterSetの項目で、Characters from Fileに指定するテキストファイルを拡張機能で作成してみよう、という内容です。

TextMeshProを使う時、アセットの形式で保存されたフォントの指定が必要になります。

このフォントアセットを作成するために、FontAssetCreatorの機能を使ってフォントを生成するのですが、そのまま作ると容量が大きくなってしまうので、必要な文字のみを指定して作ることがあると思います。

FontAssetCreatorの設定画面の、赤で囲んだ部分です。

/img/article/2018/11/12/01.png
FontAssetCreatorの画面

ここのポップアップでCharacters from Fileを選択すると、文字セットをテキストファイルで指定することができます。

この指定するテキストファイルを、エディタ拡張で作成する機能を作ろう、という内容です。

なぜこんなことをするかと言うと、容量の節約です。

使用する言語によりますが、日本語が含まれるフォントをそのままアセットにする場合、収録されている文字が多いため結構なサイズになってしまいます。

FontAtlasCreatorの設定にもよりますが、自分の場合は16MBほどありました。

最近の公開できるアプリサイズは大きくなってきたものの、フォントのみでかなりの容量になります。

なので、使う文字のフォントだけを収録してあげたら大幅な容量節約になります。

例. 使用している日本語が「はい」と「いいえ」のみ

極端な例ですが、自分で作っているアプリ内で日本語が「はい」と「いいえ」のみを使っている時、ほとんどの日本語が収録されているフォントアセットを作っても、使わない文字に容量を使ってしまうことになります(使わないひらがな、カタカナ、漢字、記号など)

こんな時は、「はい」と「いいえ」が入ったものを使えば、容量節約になります。

前提

今回は、プログラムで使用されている文言が一箇所に集約されているということで進めます。

なので、文言は全て定数に定義していて、表示する時は必ず定数から文言を取得して表示する、という内容で説明します。

ソースコード

Editorディレクトリのソース

ソースコードを表示

using System.Collections.Generic;
using System.IO;
using System.Text;
using System;
using UnityEditor;
using UnityEngine;

public class ExtTool
{
    [MenuItem("SampleTool/CreateCharSet")]
    public static void CreateCharSet()
    {
        // 定数で使用されている文字を集める
        // SortedSetを使い、使用する文字の重複を省く
        var sortedSet = new SortedSet<char>();
        foreach (var value in Enum.GetValues(typeof(SampleEMessageKey)))
        {
            var text = SampleMessage.GetText((SampleEMessageKey)value);
            foreach (char c in text)
            {
                sortedSet.Add(c);
            }
        }

        // 使用する文字を結合して、文字列にする
        string fontCharacters = "";
        foreach (var c in sortedSet)
        {
            fontCharacters += c;
        }

        // テキストファイルへ書き出し
        var fileInfo = new FileInfo(Application.dataPath + "/charset.txt");
        using (StreamWriter sw = fileInfo.CreateText())
        {
            sw.WriteLine(fontCharacters);
            sw.Flush();
            sw.Close();
        }

        AssetDatabase.Refresh();
    }
}

Scriptsディレクトリのソース

ソースコードを表示

public enum SampleEMessageKey
{
    MSG_ID_1,   // 共通文言 「はい」
    MSG_ID_2,   // 共通文言 「いいえ」
    MSG_ID_3,   // ホーム画面 「こんにちは」
    MSG_ID_4,   // ホーム画面 メニュー1 「ぼうけん」
    MSG_ID_5,   // ホーム画面 メニュー2 「どうぐ」
}
using UnityEngine;

public class SampleMessage
{
    public static string GetText(SampleEMessageKey key)
    {
        switch (key)
        {
            case SampleEMessageKey.MSG_ID_1:   // 共通文言 「はい」
                return "はい";
            case SampleEMessageKey.MSG_ID_2:   // 共通文言 「いいえ」
                return "いいえ";
            case SampleEMessageKey.MSG_ID_3:   // ホーム画面 「こんにちは」
                return "こんにちは";
            case SampleEMessageKey.MSG_ID_4:   // ホーム画面 メニュー1 「ぼうけん」
                return "ぼうけん";
            case SampleEMessageKey.MSG_ID_5:   // ホーム画面 メニュー2 「どうぐ」
                return "どうぐ";
            default:
                return "なし";
        }
    }
}

コードの説明

Scripts

SampleEMessageKey.cs

共通文言を定義している定数です。

後述のSampleMessage.csで必要な文言を取得するために使います。

SampleMessage.cs

GetTextメソッドで、引数の定数に対する文言を取得します。

日本語以外を使う時、この中で条件分岐を使えばローカライズっぽいことができます。

ただ、この作りだとswitchが肥大化して大変なことになりそうなので、文言が多い場合は別のアプローチを考えた方がいいかもしれません。

Editor

ExtTools.cs

文字セットをファイルへ書き出すクラスです。

定数から文言を取得して、使用している文言をSortedSetに登録して、最後にファイルへ書き出しています。

重複を省き、文字の順で並べたいので、SortedSetクラスを使っています。

文字の順で並んでいると、diffが確認しやすいと思っていたのですが、追加する文字が多くなるとあまり実感が得られなかったので、こだわるところではなかったかな。。。と思っています。

まとめ

今回は、FontAtlasCreatorでフォントアセットを作る時に指定する文字セットのテキストファイルを、エディタ拡張で作るという内容でした。

記事の内容は日本語のみでしたが、ローカライズしている時はローカライズしている分もテキストに含めてあげればいいですね。
ただ、これはアプリ内で使う文字が決まっている時に有効な方法です。

ユーザ名など、ユーザから入力される場合は使える文字を制限しないと使えないです。
こういう時は、必要になったらまた考えます。

今回の内容で、少しでも開発の時間短縮なればと思います。

それでは、このへんで。
バイナリー!



関連した記事