概要
Unityのテキスト表示で、顔文字とか、なんかよくわからない難しい漢字を表示しようとすると、Text表示でエラーが出たり、TextMeshProが通称"豆腐"になったりします。(下図は、アルファベットしか対応してないフォントで「TextMeshぷろ」と入力したときの表示)
新しくリリースされたソシャゲなどでユーザー名を入力する際に、表示対応してなさそうな様々な文字を入力してアプリをクラッシュさせる遊びを皆さん嗜んでおられると思いますが、自分のゲームでやられると嫌なのでしっかり対策しましょう。
様々方針はあると思いますが、文字の扱いって歴史が深くてできれば関わりたくないので、Unityが用意してくれてるAPIを利用してみます。
フォントに文字が含まれてるか返すメソッド
UnityEngine.Font.HasCharacter
UnityEngine.UI.Textを使用する際に使えます。
char
を引数に渡して、それがフォントに含まれる文字かどうかのbool
を返してくれます。
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
[SerializeField] private Text text;
private void Start()
{
// なんかすごい難しそうな漢字
var userInputChar = '亹';
// この文字は表示できる?
var canRender = text.font.HasCharacter(userInputChar);
}
}
フォントに含まれてるなら表示できるし、含まれてないなら表示できないっていうのが一番素直なので、特定の文字はどうしても使わせたくないとか特別な事情が無いならこれで十分かなと思います。
TMPro.TMP_FontAsset.HasCharacter
TextMeshProを使用する際にも同様のメソッドを使用できます。プロパティ名はfont
と、前述のTextと同じですが型は違います。
なお、オプション引数として、「フォールバックのフォントも検索するか」、「フォントアセットに動的に文字を追加するか」を選べます(デフォルトfalse)。
using UnityEngine;
using TMPro;
public class Test : MonoBehaviour
{
[SerializeField] private TextMeshPro tpm;
private void Start()
{
// なんかすごい難しそうな漢字
var userInputChar = '亹';
// この文字は表示できる?
var canRender = tmp.font.HasCharacter(userInputChar);
}
}
TMPro版はさらにstring
を渡して文字列を一括で判定してくれる、HasCharacters
もあります。
using UnityEngine;
using TMPro;
public class Test : MonoBehaviour
{
[SerializeField] private TextMeshPro tpm;
private void Start()
{
// なんかすごい難しそうな文字列
var userInputString = "齷齪";
// この文字列は表示できる?(1つでも表示できない文字があればfalse。そうでなければtrue)
var canRender = tmp.font.HasCharacters(userInputString);
}
}
おわり
こういうメソッドをUnityサイドが文字表示するために用意してるのは考えてみれば当たり前の話ですが、実はpublicで公開されてるので我々Unityユーザーも使えるんですね。文字表示に限らず、もしかしてUnityに元からあるんじゃね?と思える処理なら、一度Unityが公開しているソースコードを調べてみるのは悪くないと思います。
とはいえ調べた結果internalで宣言されてるのを見つけて悲しい気持ちになる可能性はなくはないです。