今回は「OSにインストールされたフォント」をUnityで使用する方法についてです。
フォントはゲームの第二の顔
フォントは実は結構重要な要素の一つで、AppStoreやGooglePlayで売上ランキングに乗るようなアプリは結構ゲームにマッチしたフォントを使用していることが多かったりします。
また視認性なども大きく異なり、文章が読みやすいフォントや、視認しやすいフォント、ゲームの味として採用されるフォントなど、フォントは結構重要な要素の一つです。
で、Unityエディターを長年見続けてフォントに見慣れてくると、見慣れたフォントが出てくるだけでウンザリする事があります。Unityは基本的にArialでArialに無いフォントは特定のフォントにフォールバックするので、フォントを変更していないとだいたい同じフォントが使われてしまう訳です。
【Unity道場 2017】伝える!伝わる!フォント表現入門より
なるほど!さっそくフォントを変更しよう!!となる訳ですが、ここには一つ注意すべき点があります。ほとんどのフォントにはライセンスが付いてくるという事です。
自分の知る範囲では商業用は兎も角、無料で配布してるOR仕様が可能なフォントは利用する事は出来ますがアプリに同梱する事を禁止してる事が多いです。そういったフォントは基本的に使用できません。
また漢字の収録数も問題になります。幾つかの常用漢字は含まれますが「全て漢字」のとなると含まれていない物が多いです。
フォントに含まれていない漢字は自動的にフォールバックしてシステムフォントが使われてしまうので、途中まで独特なフォントが唐突にゴシックになるなんてことも起こりえます。
そうだ、全部システムフォントを使おう
良いフォントを使用したいがフォントを同梱するのはアレ…という場合の力技対策で、システムフォントを使用するというアイディアがあります。
つまり、フォントを含められないならOSにプリインストールされてるフォントを使用して文字を表現するというものです。OSのフォントは漢字も揃っている事が多いですし、同梱してないので再配布の問題もありません。
まぁOSに含まれていない事もあるんですが…
で、通常はUnity指定のフォントにフォールバックされてしまうのですが、フォールバック先を強引にこちらで指定する方法についてです。
手順
まず適当なフォントを用意します。
StandardAssetsのUtilityに何気に幾つかフォントがあるので、ソレでも良いです。
次にフォントの中身に何も含めないようにします。
Incl.Font Dataのチェックを外すと「フォントはゲームをプレイする端末にインストールされているものを使う」判断になり、フォントファイルの中身が空になります。
これで元々のフォントが何であれ使用することが出来ます。
あとはFont Namesに使用したいフォントを登録します。
複数のフォントを登録する(例えば基本的にRobotoを使用するが一部でSunsのフォントを使用する)といった場合には、カンマで区切ります。なおフォント名は英語で入力します。
下の図ではInpactフォントを使用していますが、Inpactは日本語に対応していないので日本語をMSP明朝にフォールバックしています。
フォント名が分からない場合は、下のが参考になるかもしれません。また、Font.GetOSInstalledFontNamesでインストールされてるフォント一覧を確認出来ます。
フォールバックのやりすぎにご注意
FontNamesに任意のフォントを登録することで、フォールバック(代替で表示)する事ができるようになる訳ですが、一つ注意すべき点があります。
FontNamesに登録したフォントは全てのフォントがメモリに自動的にロードされてしまうので、ココに大きなフォントを沢山指定するとメモリを大きく消費するかもしれません。
もし中国語や日本語、韓国語の全てのフォントを一つのフォントで賄おうとする場合には注意が必要そうです。
CreateDynamicFontFromOSFontは使わないの?
今回は割とトリッキーなアプローチを紹介しましたが、似たような機能でCreateDynamicFontFromOSFontという「OSにインストール済のフォントを元にFontを作成する」という正にソレなAPIがあります。
実際コレを使用すればMS PMinchoのフォントをロードして使用するという事も可能です。ただコレはフロートしては面倒な所があって、
- フォントを管理する制御システムを用意して、そこにフォントを集約しないとメモリ消費と描画負荷がどんどん上がる
- UIにフォントを登録する仕組みが別途必要になる
- ゲームを再生しないと動作が確認出来ない
という点があります。
フォント管理システムですが、これはフォントが「1フォントにつき1枚のテクスチャ」になる事が問題となります。
例えば2つのフォントがあったとして、片方が「ABC」もう片方が「BCD」と表示した時、2つは「BC」という共通した文字列を持っているのにも関わらずデータを共有せず異なる文字列として扱ってしまっています。
これはフォントのリビルドを回避するのに使えるアプローチですが、特に気にせずガンガンFontを生成すると、色々とメモリがマッハになります。
なお、個人的には、この手のアセットが関わるリソースマネージャー系はScriptableObjectに格納するのが良いと思います。参照した地点でデータがロードできて、アンロードもソコまで複雑化しない。
WebGLは?
この記事を書いたキッカケですが、Unity WebGLではシステムフォント系の機能が全く使えないので、こういったフォールバックの仕組みは使えません。
Webフォント系も使えないっぽいので、基本的にコンテンツに同梱して使用する必要があります。
関連
文字を表示しようと思ったらTextMeshProも良いかもしれません。BMPフォントなどが代表されるように、印刷したら大丈夫になるフォントは結構あります。
tsubakit1.hateblo.jp文字は大事だと説明してくれる資料
tsubakit1.hateblo.jp文字表示機能についてです