質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

Unity: リスト内の複数の要素(文章)をローカライゼーションするアドバイスが欲しいです。

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 424

Kotaro22

score 19

イメージ説明

イメージ説明

上記の設定から下記のイメージの様に文章を作成し、シーン内のテキストにリスト内の24の文章が表示される様に設定したのですがプログラミングの経験も浅くUnityでの初めてのアプリ作成でもあり、どの様にローカライゼーションするべきか分からずにいます。I2 Localizationをインポートしてみたのですがリストへの適用は難しそうだったのでここで質問させてもらいました。

イメージ説明

Localization++も使用しようと試してみたのですが現在の自分では柔軟に使いこなせそうにありませんでした。C#やUnityでのローカライゼーションに明るい方がいましたらアドバイスを頂けないでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

汎用性に欠けちゃうんですが、リストをそのまま使いまわしたいってことなら最悪既存クラスの拡張で対応とか…は駄目ですかね? 24個ぐらいならこれでも書けるかなーとは思うのですが

    [System.Serializable]
    public class Question {
        public string fact;   // 日本語
        public string factEN; // 英語
        public string factCN; // 中国語
    }

    Language currentLanguage = Language.JP; // とりあえず日本語選択

    enum Language {
        JP,
        EN,
        CN
    }


    void SetCurrentQuestion() {
        currentQuestion = unansweredQuestions[currentQuestionIndex];
        switch (currentLanguage) {
            case Language.EN:
                factText.text = currentQuestion.factEN;
                break;
            case Language.CN:
                factText.text = currentQuestion.factCN;
                break;
            default:
                factText.text = currentQuestion.fact;
                break;
        }
    }

もっと汎用的や拡張性を考えると、キーなどを決めて対応する言語を入力して外部に翻訳データを作っていくとかになると思います。

主キー,日本語,英語
fact1,あなたは犬好き?,Do you like dog?
fact2,あなたは猫好き?,Do you like cat?

質問1のときはfact1の行のデータを取得して、日本語なら2列目のテキスト、英語なら3列目のテキストを引っ張ってくる…みたいなやり方でしょうか。

追記(2019/10/31)

思いついた内容を実装したサンプルなので、これが必ずしも正解というわけではありませんが外部化してみるテストです。(質問者さんのListを使いまわしたいという願望からは外れます)

まず、翻訳用データのテキストファィルを2つ作成します。UTF-8などの文字コードで保存してください。
保存先はアセットフォルダに【Resources】というフォルダを作成し、更に【Language】というフォルダを作成し、【language_**.txt】という形式で保存します。
(例:【Resources\Language\language_ja.txt】)

● language_ja.txt

fact1,こんにちは
fact2,おはよう!
fact3,さよなら!
fact4,僕ドラえもんです
fact5,僕はおにぎりが大好きなんだなぁ
fact6,おっす、おら悟空!
fact7,月にかわってお仕置きよ!

● language_en.txt

fact1,Hello!
fact2,Good morning.
fact3,Good-bye.
fact4,Hello, I'm Doraemon
fact5,I love Riceball
fact6,Hi. this is Goku!
fact7,In the name of the Moon I shall punish you!

テキストIDに対するテキストがそれぞれ保存されていることがわかります。
(例: fact1 であれば こんにちは (英語ならHello!))

では、これを読み込んで表示するスクリプトを書いてみます。

● LocalizeTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LocalizeTest : MonoBehaviour {

    // 現在の言語設定
    string currentLanguage = "ja"; // ja,en

    // キーを並べた会話データ。この順番に会話が進む
    private List<string> gameTextID = new List<string>() {
        "fact1",
        "fact3",
        "fact4",
        "fact2",
        "fact5",
        "fact6",
        "fact7",
    };

    // 翻訳データ。選択中の言語のデータがロードされる
    public Dictionary<string, string> textData = new Dictionary<string, string>();

    // 会話の現在の場所を表す変数
    int clickCounter = 0;

    private void Start() {
        Debug.Log("現在の言語は " + currentLanguage + " です。マウスクリックで次の会話が表示されます");
        LoadLanguageData();
    }

    // 翻訳データをテキストファイルから読み込む
    private void LoadLanguageData() {

        // Resources/Language/language_*.txt を読み込んでいる
        var loadLanguageText = Resources.Load<TextAsset>("Language/language_" + currentLanguage);

        // 読み込んだテキストデータを改行で区切って配列に代入
        var languageTextData = loadLanguageText.text.Split('\n');

        // キー,テキストデータ という構成なので、更に,で区切ってDictionaryに入れる
        foreach (string text in languageTextData) {
            // 得た1行を更にカンマで区切る。
            var myText = text.Split(',');
            // 区切られた文字列は テキストID と テキスト なのでDictionaryに追加
            textData.Add(myText[0], myText[1]);
        }

    }

    void Update() {

        // マウスクリックで会話が進む
        if (Input.GetMouseButtonDown(0)) {

            // テキストデータのキーから現在の会話IDをチェック
            var currentText = textData[gameTextID[clickCounter]];

            // データが見つからなければ戻す
            if (currentText == null || currentText == "") { return; }

            // テキストを表示
            Debug.Log("[" + gameTextID[clickCounter] + "]" + currentText);

            // 会話を1つすすめる。カウンターが会話データよりも多ければ0に戻す
            clickCounter = clickCounter + 1 >= gameTextID.Count ? 0 : clickCounter + 1;
        }

    }

}


適当なオブジェクトにアタッチして起動したら画面をクリックしてみてください。コンソールに会話文がどんどん表示されるかと思います。

currentLanguage で現在の言語設定を設定しています。jaなら日本語、enなら英語データをロードしにいきます。

キーをあてがって会話文を外部化したので、呼び出したい会話をキーでセットしておけば言語設定に沿った内容が表示されることが期待できます。gameTextIDでは会話の順番をテキストIDで指定しています。

翻訳データ取得のところでは【Resources\Language\language_ja.txt】などのテキストファイルをロードして、その内容を改行ごとにわけて配列に代入しさらにそれをカンマで区切ってDictionary<string,string>にキーとテキストとして代入していきます。
※ よく考えると今回は英語ローカライズとかもするのでカンマは悪手でした、何か区切り文字を他のものに変えても良さそうです(|とか)

あとは画面クリックする度に、会話の順番のテキストIDを使ってDictionaryから該当するテキストデータを探し、それを表示しています。外部化するメリットは、たとえば中国語対応をしたいなと思ったらlanguage_cn.txt を追加して中身をガリガリ書けば良いという感じのところです。

ゲームの日本語化作業とかで得た断片的な知識で書いているだけで、ローカライズが仕事とかではないのであまり鵜呑みにせずこんなこと思いついた人がいる程度に見て頂ければと思います

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/30 17:23

    >hogefugapiyoさん

    回答ありがとうございます。既存のクラスを拡張した方法を少し自分なりに応用して多言語化しようと思います。

    2つ目のアプローチの仕方についての質問になるのですが、外部に翻訳データを作った場合はforeachやforで24回ループさせて表示させたいテキストへ反映させるのかなとぼんやりイメージするのですが可能であれば少し具体的なスクリプトをシェアしてもらい理解を深めさせてもらえないでしょうか?

    キャンセル

  • 2019/10/31 10:35

    思いついたものを追記しました。あくまでこんなやり方もできるかもねぐらいに思って頂ければ幸いです

    キャンセル

  • 2019/10/31 17:05

    >hogefugapiyoさん

    事細かくアドバイスをしていただき本当にありがとうございます。シェアして頂いたものをしっかり参照し、今後円滑にローカライズをしていける様ステップアップしていきたいと思います。ローカライズに関する理解を深めるためにとても参考になりました。どうもありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • C#に関する質問
  • Unity: リスト内の複数の要素(文章)をローカライゼーションするアドバイスが欲しいです。