[Unity] LocalizationでSmartStringをシンプルに使う

[Unity] LocalizationでSmart Stringをシンプルに使う

Unityで多言語対応をしたい時、大体はUnity標準で提供されているLocalizationを使用すると思います。

かく言う自分もLocalizationにはお世話になってますが、今回はちょっと応用的な使い方の話です。

今回検証したUnityバージョンは6000.3.4f1になります、バージョンが違っていても細かい所で操作が異なるだけでスクリプトは共通で使えるはず。

変数を表示したい

例えばなんですが、スコア表示の文字列を多言語対応したとして、日本語では「スコア: 100点」、英語では「Score: 100pt」みたいに表示したいとします。

この場合100という数字以外は全て異なっているので、これをSmart String無しで実現しようとすると結構面倒だしコードも読みづらい。

そういった場合にはちゃんとその為の機能もLocalizationにはあって、それがSmart Stringです。

Smart Stringとは

Smart Stringとは、Localization Tablesで設定できる動的な文字列生成機能です。

Localization TablesでSmart Stringを利用したい場合は、そのKeyにあるいずれかの言語の縦三点リーダーをクリック→Smart String (All)をクリックすれば、そのKeyの全言語でSmart Stringが有効になります。

Smart Stringが有効の場合は縦三点リーダーの左に「{S}」と表示されます。

特定の言語だけやりたいパターンはあまりないとは思いますが、その場合はSmart String (All)ではなく、有効にしたい言語の縦三点リーダーをクリック→Smart String (言語)で個別に有効にできます。

Smart Stringの使い方

Localization Tablesの設定

テキストボックスにSmart String対応の書き方をします、先の例だとJapanese (ja)には「スコア: {score}点」、English (en)には「Score: {score}pt」みたいに書きます。

SmartStringを有効にし変数を記載した

中括弧を使って変数を宣言する形です、変数名は同じKey内だけで共有されるので、他のKeyで重複していても問題ありません。

※なので別のKeyで同じくscoreという変数を使っていても、値の共有も同じくされない

Localize String Eventの設定

さっき作成したLocalization Tablesを使用するText Mesh ProでLocalizeを有効にし、Localize String Eventコンポーネントを追加します。

String ReferenceでさっきのKeyを指定すれば、ここまでは通常通りの多言語対応になりますね。

ここからSmart String特有の設定をもう一つ加えます。

Localize String Eventの中にLocal Variablesというのがありますが、ここで先の例の場合、プラスマークを押して選択肢の中のIntegerを選び、variable nameに「score」と入力します。

Localize String EventのLocal VariablesにInt型の変数scoreを追加

Integerの所は初期値の0のままで大丈夫です、もし初期値が他に決まっている場合はここで入れておくか、この次で作成するスクリプトを初期化時に呼び出すかをして下さい。

スクリプトの作成

最後の工程です、Localize String Eventにスクリプト上で値を渡す為の汎用的なスクリプトを作成します。

これは無くても値の変更は可能です、毎回同様の処理をするか別のスクリプトに書き足すとかでも良いです。

using UnityEngine;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.SmartFormat.PersistentVariables;

/// <summary>
/// ローカライズ文字のSmartStringに値を渡すクラス
/// </summary>
[RequireComponent(typeof(LocalizeStringEvent))]
public class LocalizedVariablesProvider : MonoBehaviour
{
    private LocalizeStringEvent _event;

    private void Awake()
    {
        _event = GetComponent<LocalizeStringEvent>();
    }

    /// <summary>
    /// keyを指定してSmartStringの値を設定する
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    public void SetValue(string key, int value)
    {
        if (_event.StringReference.TryGetValue(key, out var variable) && variable is IntVariable intVariable)
        {
            intVariable.Value = value;
        }
        else
        {
            Debug.LogWarning($"Localize String Eventに未登録の変数: {key}");
        }
    }
}

このスクリプトを作成し、Smart Stringを設定したLocalize String EventのあるText Mesh Proがアタッチされたゲームオブジェクトに追加でこのスクリプトをアタッチします。

GetComponentで自身のオブジェクトのコンポーネントを取得してますが、ここを変えればスクリプトを同じゲームオブジェクトにアタッチしなくても良くなるので、状況に応じて変えて下さい。

後はこのスクリプトをインスペクター上で変数として保持するかして、呼び出し側でSetValueを実行すればリアルタイムに各言語間で変数の設定が可能になります。

この方法以外にもLocalize String EventのStringReferenceを使う手もありますが、その場合は値の変更にRefreshStringの呼び出しが必要で、こちらの方が初回の手間はかかるけど即反映なので楽だと思います。

またRefreshStringは呼び出しの際にテーブルの参照と文字列生成処理が毎回されるようなので、例えばUpdate関数内で呼び出すにはややコストが高いです。

今回のスクリプトでは一応複数の値を設定できるようにしていますが、一つのテキストに一つの変数であればSetValueのkey引数は不要にできます。

また設定する値は今回intに固定してしまってますが、ここも変更すれば様々な型に対応も可能です。

私のケースだと、ほぼほぼ変数は数値のみなので、これで事足りました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です