Unity の Localization でスクリプトから多言語化表示テキストを切り替える
※ これは 2022/10/13 時点の Unity 2022.1.20f1 Localization v1.3.2 の情報です
最新版では動作が異なる可能性がありますのでご注意ください
前回、文字列とフォントが一緒に切り替えることができたが、あくまで静的な多言語化
今回はスクリプトの中で表示リソースを切り替えてみたい
例によってこの「モカ」ボタンが押されたら「カフェ」に表示を切り替えてみたい
まず Localization の Recommended バージョンだと機能が古いので v.1.3.2 にアップデートする
Unity の Package Manager を開き、左上の「+」ボタンから 「Add package by name」を選択し、com.unity.localization
のバージョン 1.3.2
を指定して Add ボタン押下
これでバージョンアップ完了
次に String Table に Cafe の文言を追加
あとは Test.cs
を下記のように変更し、ボタンが押されたら多言語化リソースを切り替えるようにする
using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Localization; using UnityEngine.Localization.Components; using UnityEngine.Localization.Settings; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.UI; public class Test : MonoBehaviour { [SerializeField] private Image cafeImage = null; [SerializeField] private Image mochaImage = null; [SerializeField] private LocalizeStringEvent labelEvent = null; private Image thumbnailImage = null; private AsyncOperationHandle<Sprite> handle = default; private const string RemoteLoadPath = @"http://localhost/StandaloneWindows64/{0}/"; private static string OriginalRootPath = null; private static string CurrentRootPath = null; private AssetBundle currentBundle = null; private string currentName = null; private Hash128 currentHash = default; public async void Start() { // Addresables 初期化 var locator = await Addressables.InitializeAsync().Task; // 初期化時のルートパス取得 var info = Addressables.GetLocatorInfo(locator.LocatorId); OriginalRootPath = info.HashLocation.InternalId.Replace(Path.GetFileName(info.HashLocation.InternalId), ""); // アドレス書き換えを有効化 Addressables.InternalIdTransformFunc = MylIdTransform; // 日本語指定 await LocalizationSettings.InitializationOperation.Task; LocalizationSettings.SelectedLocale = Locale.CreateLocale("ja"); await SetCatAsset("Cafe"); } private static string MylIdTransform(IResourceLocation location) { // ルートパスを置き換える if (location.InternalId.StartsWith(OriginalRootPath)) { return location.InternalId.Replace(OriginalRootPath, CurrentRootPath); } return location.InternalId; } private async Task SetCatAsset(string catName) { Cat.Name = catName; this.thumbnailImage = catName switch { "Cafe" => this.cafeImage, "Mocha" => this.mochaImage, _ => null }; // ルートパスの再評価 CurrentRootPath = string.Format(RemoteLoadPath, Cat.Name); // リモートカタログに変更があれば更新する var catalogs = await Addressables.CheckForCatalogUpdates(true).Task; if (catalogs != null && catalogs.Count > 0) { var locators = await Addressables.UpdateCatalogs(catalogs, true).Task; // リモートアセットの取得先を確認 if (locators[0].Locate("Assets/Sprites/cat.png", typeof(Sprite), out var locations)) { // リモートアセットの URL は Dependencies に入っている foreach(var location in locations[0].Dependencies) { UnityEngine.Debug.Log($"--------------> uri={Addressables.InternalIdTransformFunc(location)}"); if (location.Data is AssetBundleRequestOptions sizeData) { #if UNITY_EDITOR EditorUtility.DisplayDialog($"{location.PrimaryKey}", $"{sizeData.BundleSize:#,0} bytes", "OK"); #endif } } var option = locations .SelectMany(x => x.Dependencies) .Select(x => x.Data) .OfType<AssetBundleRequestOptions>() .First(); var newName = option.BundleName; var newHash = Hash128.Parse(option.Hash); if (this.currentBundle != null) { UnityEngine.Debug.Log($"--------------> {this.currentName}【{this.currentHash}】 -> {newName}【{newHash}】"); // 同じ名前で内容(Hash)が異なる AssetBundle がないか調べる if (this.currentName.Equals(newName) && this.currentHash != newHash) { // アセットのインスタンスは残したまま、古い AssetBundle を解放してキャッシュからも破棄する this.currentBundle.Unload(false); if (Caching.IsVersionCached(newName, this.currentHash)) { Caching.ClearCachedVersion(newName, this.currentHash); } } } // BundleName と Hash を保持しておく this.currentName = newName; this.currentHash = newHash; } } AsyncOperationHandle download = default; try { // AssetBundle を抽出するために Load 前に Download download = Addressables.DownloadDependenciesAsync("Assets/Sprites/cat.png"); var resources = await download.Task as List<IAssetBundleResource>; if (resources.Count < 1) { return; } this.currentBundle = resources[0].GetAssetBundle(); // Addressables 経由で Sprite を読み込んで表示 this.handle = Addressables.LoadAssetAsync<Sprite>("Assets/Sprites/cat.png"); this.thumbnailImage.sprite = await this.handle.Task; } finally { // Load が終わったら Download ハンドルは用済みなので解放 if (download.IsValid()) { Addressables.Release(download); } } } /// <summary> /// Mocha ボタン押下イベントハンドラ /// </summary> public async void OnMochaButtonClicked() { await SetCatAsset("Mocha"); // Cafe にラベル変更 this.labelEvent.SetTable("StringTable"); this.labelEvent.SetEntry("Cafe"); } public void OnDestroy() { // いらなくなったら handle を Release する if (this.handle.IsValid()) { Addressables.Release(this.handle); } } }
重要なのは下記
// Cafe にラベル変更 this.labelEvent.SetTable("StringTable"); this.labelEvent.SetEntry("Cafe");
StringTable が変わらないので LocalizeStringEvent.SetEntry()
だけでもいいけど一応 LocalizeStringEvent.SetTable()
もして切り替える
最後に Test.cs の labelEvent
に忘れずにボタンラベルの LocalizeStringEvent
を差しておく
これでお試し
ちゃんと日本語でラベルが切り替わった