このガイドでは、Unity Localization のセットアップと設定について説明します。ロケール、String および Asset テーブル、Addressables 統合、Asset テーブルを使用した CJK フォントサポートが含まれます。
0. パッケージインストール確認
他の作業を行う前に、Localization パッケージがインストールされていることを確認してください。このスキルの多くの API は、パッケージが存在しない場合、黙って失敗したり、混乱を招くエラーをスローしたりします。
- パッケージマネージャーに問い合わせるのではなく、プロジェクトを読み取って確認します。
Packages/packages-lock.json内のcom.unity.localizationを探してください。このファイルには、Unity が実際に解決した内容が記録されており、プレーンな JSON であるため、エディターや非同期呼び出しを必要とせずに読み取ることができます。(Packages/manifest.jsonは 要求された 内容のみを記録するため、ロックファイルを確認してください。) - 欠落している場合にインストール:
UnityEditor.PackageManager.Client.Add("com.unity.localization")。 - 適切に待機します。
Client.AddとClient.Listは 非同期 です。返されるリクエストは、呼び出しが戻った時点でもInProgress状態であるため、同じステートメントで結果を読み取っても意味がありません。IsCompletedでビジーウェイトしないでください。実行中のメインスレッドをブロックします。代わりに、インストールを実行したら一度戻り、後の呼び出しでpackages-lock.jsonをポーリングして ID が表示されるまで待ちます。インストールによってドメインリロードもトリガーされるため、最初の数回のポーリングは失敗することが予想されます。新規インストールは通常、数秒で解決します。 - タイプが実際にロードされていることを確認 してから使用します。ロックファイルはアセンブリの準備ができる前に書き込まれる可能性があるためです:
var t = System.Type.GetType( "UnityEngine.Localization.Settings.LocalizationSettings, Unity.Localization"); return t != null ? "ready" : "not loaded yet";readyが返されるまで先に進まないでください。
1. Localization Settings と Locales
LocalizationEditorSettings.ActiveLocalizationSettings が null の場合、それを見つけるか作成する必要があります:
- 検索:
AssetDatabase.FindAssets("t:LocalizationSettings", new[] { "Assets" })を使用します。見つかった場合は、最初のものをロードし、LocalizationEditorSettings.ActiveLocalizationSettingsに割り当てます。- 常に検索フォルダを指定してください。 スコープ指定なしの
FindAssetsは読み取り専用パッケージを含むプロジェクト全体を検索するため、パッケージからアセットを返し、編集できないものをプロジェクトが指すことになる可能性があります。これは、このスキル内のすべてのFindAssets呼び出しに適用されます。
- 常に検索フォルダを指定してください。 スコープ指定なしの
- 作成: 見つからない場合は、新しいインスタンスを作成し、
Assets/Localization/LocalizationSettings.assetに保存します。ScriptableObject.CreateInstance<LocalizationSettings>()の後にAssetDatabase.CreateAsset()を使用します。 - アクティブ化:
LocalizationEditorSettings.ActiveLocalizationSettings = settingsを設定します。 - ロケール: ロケール(en、fr、de など)が存在することを確認します。存在しない場合は作成し、
LocalizationEditorSettings.AddLocale(locale)を使用して設定に追加します。
2. Localization テーブルの変更
String または Asset テーブルへのプログラムによる変更は、エディターに通知する必要があります。 プロジェクトに既存のものがない限り、必要なアセットテーブルを常に作成してください。
安全なデータ投入パターン
データセットからテーブルにデータを投入する場合、Locale.Identifier.Code で明示的に一致させてください。GetLocales() の順序は入力データ配列と一致することが保証されていません。一致すると仮定すると、デバッグが非常に困難なサイレントなデータ不一致が発生します。
Asset テーブル の場合、アセットの GUID を使用します:table.GetEntry(sharedId) ?? table.AddEntry(sharedId, guid);。
リフレッシュと通知
変更(キーの追加、値の更新)後は、エディターに内部状態をリフレッシュするよう通知します。これをスキップすると、エディターは次の再インポートまで古いデータを表示し続けます。
- 変更された各
Tableに対してEditorUtility.SetDirty(collection)、EditorUtility.SetDirty(collection.SharedData)を呼び出します。 - Unity 6+ の通知:
LocalizationEditorSettings.EditorEvents.RaiseCollectionModified(sender, collection); - 最後に必ず
AssetDatabase.SaveAssets()を呼び出します。
3. UI ローカリゼーションとレイアウト
名前空間と競合
- 名前は常に完全修飾してください:
UnityEngine.UI.Image、UnityEngine.UI.VerticalLayoutGroup、UnityEngine.UI.ScrollRect、UnityEngine.UI.Mask、UnityEngine.UI.CanvasScaler、UnityEngine.UI.GraphicRaycaster、UnityEngine.UI.ContentSizeFitter、UnityEngine.UI.LayoutRebuilderなどを使用します。 UnityEngine.UIは名前空間であると同時にクラスコンテナでもあるため、非修飾名はCS0118(名前空間が型として使用されている)を生成します。完全修飾によりこれを完全に回避できます。- シングルインスタンス: 常に
GameObject.Find("YourCanvasName")をチェックし、新しいものを作成する前に古いものを破棄してください。 - ロケール切り替え:パッケージを使用し、プレビューとランタイムを分離してください。 これらは 2 つの異なるメカニズムであり、それらを混同することが、ロケール切り替えが手作業で実装されがちな理由です。
- オーサリング中にロケールをプレビューするには、Localization Scene Controls ウィンドウ(
Window > Asset Management > Localization Scene Controls)を使用します。これはエディター専用です。ランタイム機能ではないため、ゲーム自体に言語設定が必要な場合の解決策にはなりません。 - ランタイムにロケールを切り替えるには、
LocalizationSettings.SelectedLocaleを割り当てます。これがサポートされているエントリポイントであり、LocalizeStringEventを通じてバインドされたすべてのものがこれから更新されます。 - ゲームが開始するロケールを固定するには、Localization Settings アセットでスタートアップロケールセレクターを設定します。
SpecificLocaleSelectorは選択したロケールを強制するものです。デフォルトのチェーンはシステム言語を取得します。 - ロケールの状態を手動で管理しないでください。 実際のゲーム内言語メニューは問題なく、むしろ推奨されます。ただし、それは
SelectedLocaleを設定し、パッケージに変更を伝播させる限りにおいてです。禁止されているのは、独自の「現在の言語」変数を追跡し、自ら文字列を入れ替えたり、パッケージを回避したりするデバッグドロップダウンやメニューです。プロジェクト内の他の何もそれを追跡しなくなります。
- オーサリング中にロケールをプレビューするには、Localization Scene Controls ウィンドウ(
ローカライズされた文字列イベント(堅牢なバインディング)
-
コンポーネントタイプを確認: ターゲットが
TextMeshProか、従来のUnityEngine.UI.Textかを特定します。 -
正しくバインド: パブリックな
UnityEngine.Localization.Components.LocalizeStringEventコンポーネントを追加し、自分で配線します。StringReferenceをテーブルエントリに設定し、OnUpdateStringリスナーを追加して、値をテキストコンポーネント(TextMeshPro の場合はTMP_Text.text、従来の Text の場合はUnityEngine.UI.Text.text)に割り当てます。UnityEditor.Localization.Plugins.TMPro.LocalizeComponent_TMProやその UGUI 版にリフレクトしないでください。これらはinternal(Localization 1.5.12 で確認)であるため、それらにアクセスするにはアクセス制御を回避し、Unity が安定性を保証しない API に到達することになります。これはパッケージリリースごとに変更または削除される可能性があります。LocalizeStringEventはパブリックであり、配線を明示的にして同じ仕事をします。 -
レイアウト再構築: ローカライズされたテキストを設定したり、リストを設定した後は、
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(parentTransform)を呼び出して、ディメンションが更新されるようにします。
4. アジア言語フォントサポート(CJK)
CJK ロケールには TMP フォールバックフォントを避けてください。代わりに、各ロケールに固有の Asset テーブルフォントスワッピング を使用してください。フォールバックは信頼性が低く、グリフが欠落している場合のデバッグが困難です。
前提条件:TMP Essential Resources をインポートしておく必要があります
TMP API に触れる前にこれを確認してください。 これまでにインポートされたことのないプロジェクトでは、TMP_Settings.instance は null であり、TMP 呼び出しは役に立たない NullReferenceException で失敗します。TMP_FontAsset.CreateFontAsset はその一つであり、フォント作成は最初の行でエラーにより停止します。