【Unity】TextMeshProの多言語拡張の自動化について

使用パッケージ：
localization@1.4.5

フォントも選択言語によって変わる方法を紹介します。
＊localizationの基本的な使い方はここでは割愛します。

下準備：
1.AssetTableで多言語用のフォントの設置。
![スクリーンショット 2024-07-25 15.46.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757569/f9af07f2-4ad0-9418-6114-57d488d1793e.png)


2.下記にような、簡単なフォントアセット用の多言語イベントクラスを作成します。（なぜないだろう）
```c#:LocalizedTmpFontEvent.cs
using System;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;

//メニューにフォントアセット用のコンポーネントを追加します
[AddComponentMenu("Localization/Asset/" + nameof(LocalizedTmpFontEvent))]
public class LocalizedTmpFontEvent : LocalizedAssetEvent<TMP_FontAsset, LocalizedTmpFont, UnityEventTmpFont> { }

[Serializable]
public class UnityEventTmpFont : UnityEvent<TMP_FontAsset> { }

```

あとはコンポーネントをゲームオブジェクトに貼って、パラメーターを設置するだけで、自動的にフォントを設置できるようになりました：
![スクリーンショット 2024-07-25 15.50.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757569/50aaf1e7-06de-5c2b-2caa-ad4808637e11.png)

ただし、上記の設置方法はいつも同じパターンなので、こうやって自動化した方が楽になります：
```c#:
        //フォントアセットの情報を取得します（const string ASSET_FONT_TABLE = "AssetFont";）
        var asTable = LocalizationEditorSettings.GetAssetTableCollection(ASSET_FONT_TABLE);
        foreach (var row in asTable.GetRowEnumerator())
        {
            foreach (var tableEntry in row.TableEntries)
            {
                //const string ASSET_FONT_KEY = "Font";
                if (tableEntry is object && tableEntry.Key == ASSET_FONT_KEY)
                {
                    //コンポーネントの自動追加
                    var localizeEvent = lzCmp.gameObject.GetComponent<LocalizedTmpFontEvent>();
                    if (localizeEvent == null)
                        localizeEvent = Undo.AddComponent(lzCmp.gameObject, typeof(LocalizedTmpFontEvent)) as LocalizedTmpFontEvent;

                    //Editor上、Insepctorで「Localized Asset Reference」の設置とは同等
                    //TableReferenceクラス内部の演算子がオーバーロードされるので、テーブル名前の文字列で初期化可能です
                    UnityEngine.Localization.Tables.TableReference tr = asTable.name;
                    //TableReferenceとは同じく仕組み、演算子がオーバーロードされる
                    UnityEngine.Localization.Tables.TableEntryReference er = tableEntry.Key;
                    localizeEvent.AssetReference.SetReference(tr, er);

                    //Editor上、Insepctorで「Update Asset」の設置とは同等
                    var setStringMethod2 = lzCmp.GetType().GetProperty("font").GetSetMethod();
                    var methodDelegate2 = Delegate.CreateDelegate(typeof(UnityAction<TMP_FontAsset>), lzCmp, setStringMethod2) as UnityAction<TMP_FontAsset>;
                    UnityEventTools.AddPersistentListener(localizeEvent.OnUpdateAsset, methodDelegate2);
                    localizeEvent.OnUpdateAsset.SetPersistentListenerState(0, UnityEventCallState.EditorAndRuntime);

                    return true;
                }
            }
        }

        return false;
```


おまけ：
TableReferenceクラスの演算子処理
```c#:Library/PackageCache/com.unity.localization@1.4.5/Runtime/Tables/TableReference.cs

        /// <summary>
        /// Convert a table collection name into a <see cref="TableReference"/>.
        /// </summary>
        /// <param name="tableCollectionName">The name of the table.</param>
        /// <returns></returns>
        public static implicit operator TableReference(string tableCollectionName)
        {
            return new TableReference { TableCollectionName = tableCollectionName, ReferenceType = string.IsNullOrWhiteSpace(tableCollectionName) ? Type.Empty : Type.Name };
        }

```

参考資料：
https://docs.unity3d.com/ja/Packages/com.unity.localization@1.4/manual/index.html
https://light11.hatenadiary.com/entry/2022/03/10/200323
https://xrdnk.hateblo.jp/entry/localized_textmeshpro_font