技術と趣味の亜空間

主にゲームプログラミングとその周辺に関する記事を不定期で上げていきます

【TextMesh Pro】Unityで文字化けする箇所を除外する方法

f:id:Goropocha:20210325183456p:plain

概要

UnityでTextMesh Proのフォントアセットとスプライトアセットに未登録の文字列だけを除外するコードを作成しました。
上のトップ画像ではTextMehs Proデフォルトで入っているアセットデータで試しています。
Raw Textを見てみると、2行目は「日本語テキスト」と入力しましたが、フォントには入っていなので□となって文字化けしています。
また3行目3番目の絵文字は「👌」を指定しましたが、スプライトアセットに入っていないので同様に文字化けしてしまいました。
一方で今回コードで除外対応したValidated Text ではどちらもしっかりと削除されています。

文字化けの修正が目的なので、当たり前ですがフォントアセットとスプライトアセットどちらのデータにもUnicodeが設定されているのが前提です。

◆執筆時バージョン
Unity: 2019.4.18f1
TextMesh Pro: 2.1.1

コード

解説

文字列をUTF-32 BEに変換し、そこからUnicodeのスカラ値へと変換します。
これはTextMehs Proで登録した文字のUnicodeが10進数 ビッグエンディアンで管理されているためです。
変換したスカラ値をアセットのUnicodeと照合し、一致するものが無ければ削除します。

実は単純なフォントデータのチェックだけならば以下の2通りで簡単に実現できます:

  1. テキストをfor文なりで回してchar型を取得しTMP_Settings.defaultSpriteAsset.HasCharacter(char character) で判定する
  2. テキスト自体をTMP_Settings.defaultSpriteAsset.HasCharacters(string text, out List<char> missingCharacters)に代入し、 missingCharacters に足りない文字がリストアップされるので、それを見て判定する

ですが、今回は4バイト以上で形成された絵文字等も判定しないといけないのでUnicodeでまとめて対応しました。
こういった特殊な文字はテキストをfor文で回しただけでは完全な文字情報は取得できないので、絵文字1個分のUnicodeのデータをちゃんと取得できる StringInfo.GetTextElementEnumerator() を利用します。
とはいえ実はStringInfoも最新のUnicodeまでは網羅していないため、うまく取得できない文字もあります。
そういった文字はUnicodeのスカラ値へと変換する過程でオーバーフローを引き起こすので、仕方なく削除しています。(もっと良い方法があれば知りたい)