TextMeshPro を利用していると FontMaterial が大量にできてしまったりして、管理が面倒になってくるので
外部からロードできれば楽になることがあるのではと思い実装の調査をしてみました
TextMeshPro の Font Material
Font Material の 差し替えを行うことができればなんとかなりそう
public abstract class TMP_Text : MaskableGraphic public Material fontMaterial { // Return an Instance of the current material. get { return GetMaterial(m_sharedMaterial); } // Assign new font material set { if (m_sharedMaterial != null && m_sharedMaterial.GetInstanceID() == value.GetInstanceID()) return; m_sharedMaterial = value; m_padding = GetPaddingForMaterial(); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); } }
ということで 今回は Resources からのロードになりますがロードテストを行ってみる
public static class TextMeshProUtil { public static void SetMaterial(TextMeshProUGUI target, string path) { // ここのロード処理は変える必要がある var material = new Material(Resources.Load<Material>(path)); target.fontMaterial = material; } }
特に何事もなく動作した
がこれはテスト用なのでキャッシュや削除処理等を記述しないと
メモリリークしてしまう可能性があるので注意してください
アセットのサイズ
今回は Resources からのロードだから問題は無いが、これをアセットバンドル対応した場合
フォントのテクスチャがアセットに含まれてしまうため、サイズが大きくなってしまう
そのため、フォントのテクスチャの参照を外す
Shader を見てみると フォントのテクスチャは _MainText
に紐付いているためこれの参照を外してロードしてみる
_MainTex ("Font Atlas", 2D) = "white" {}
Inspector を Debug にすると手動で外せます
先ほどの処理の間に MainTexture の差し込み処理を追加しました
こちらでも問題なく動作しています
public static class TextMeshProUtil { public static void SetMaterial(TextMeshProUGUI target, string path) { // ここのロード処理は変える必要がある var material = new Material(Resources.Load<Material>(path)); material.mainTexture = target.fontMaterial.mainTexture; target.fontMaterial = material; } }
複数のフォント対応
今回フォントを差し替えることで、同じ Font Material を他のフォントに対しても適応する
ことができるため、複数のフォントを利用している場合はマテリアルの数を減らせるかもしれません
問題点
マテリアルからフォントの参照を外したため
TextMeshPro の Inspector 上で Material Preset 一覧に外したマテリアルが出てこなくなります
そのため、見た目をチェックするのが面倒になるので、アセットバンドルにする場合は
ビルド時に参照を外す対応を入れるといいかもしれません