美文网首页unityUnity3D游戏开发Unity3D与游戏开发
【案例】Unity3d官方案例之Localization Too

【案例】Unity3d官方案例之Localization Too

作者: 妄想重症患者 | 来源:发表于2018-04-28 21:50 被阅读45次

    案例来源:Localization Tools
    资源:Localization Tools资源
    界面完全可以自己弄只是没那么靓靓而已..

    Localization Tools (本地化工具),当一个游戏需要支持多语言时,使用Localization Tools可以更高效的完成多语言编辑工作。
     Hierarchy如下:
     

    资源包概览
     1、布置UI界面(如果使用资源的话无需自行布置)
     LoadingScreen初始布局如下:
      LoadingScreen初始布局

    MenuScreen布局如下:
     English版本

      English版本

    German版本

      German版本

    流程:
      1. 在LoadingScreen中选择语言;
      2. MenuScreen显示对应语言。

    2、创建JSON文件(英语和德语版)
     选择存储数据的格式,这里选择JSON用于保存不同语言下各UI对应的文本。
     例如:key为game_title的Text的文本为Quiz Spiel;
     localizedText_de.json:

    {
        "items":
        [
            {
                "key":"game_title",
                "value":"Quiz Spiel"
            },
            {
                "key":"start_button",
                "value":"Spiel Beginnen"
            }
        ]
    }
    

    localizedText_en:

    {
        "items":
        [
            {
                "key":"game_title",
                "value":"Quiz Game"
            },
            {
                "key":"start_button",
                "value":"Start Game"
            }
        ]
    }
    

    3、构建类结构来存储JSON数据:
     LocalizationData:

    [System.Serializable]
    public class LocalizationData 
    {
        public LocalizationItem[] items;        // store a localizationItem list.
    }
    
    [System.Serializable]
    public class LocalizationItem               // store a item
    {
        public string key;                      // similar to json's key
        public string value;                    // similar to json's value
    }
    

    4、构建LocalizationManager
     实现根据文件名读出对应的json数据,并将数据存入LocalizationData实例中。

    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LocalizationManager : MonoBehaviour {
    
        public static LocalizationManager instance;             // Single Instance
    
        private Dictionary<string, string> localizedText;       // data similar to json files, the first string is key, second string is value
        private bool isReady = false;                           // mark if load json data process has finished.
        private string missingTextString = "Localized text not found."; // default result to return
    
        void Awake()
        {
            if (instance == null) {
                instance = this;
            } else if (instance != this) {
                Destroy (gameObject);
            }
    
            DontDestroyOnLoad (gameObject);                     // when load another scene, not destroy this manager instance.
        }
    
        public void LoadLocalizedText(string fileName)          // filename: json file name, remember to add ".json"
        {
            localizedText = new Dictionary<string, string> ();
            string filePath = Path.Combine (Application.streamingAssetsPath, fileName);     // get absolutly path of json file. json file store in Assets/StreamingAssets
    
            if (File.Exists (filePath)) {
                string dataAsJson = File.ReadAllText (filePath);    // read all text from json file.
                LocalizationData loadedData = JsonUtility.FromJson<LocalizationData> (dataAsJson);  // transform the data from tpye string to LocalizationData
    
                for (int i = 0; i < loadedData.items.Length; i++) {
                    localizedText.Add (loadedData.items [i].key, loadedData.items [i].value);   // ergodic all data an store it into localizedText
                }
    
                Debug.Log ("Data loaded, dictionary contains: " + localizedText.Count + " entries.");    // show how many item loaded success.
            } else {
                Debug.LogError ("Cannot find file!");  // show error.
            }
    
            isReady = true;             // After finished json loaded, set the mark to true,so the MenuScreen scene can be loaded.
        }
    
        public string GetLocalizedValue(string key)     // return value according the key.
        {
            string result = missingTextString;
            if (localizedText.ContainsKey (key)) {
                result = localizedText [key];
            }
    
            return result;
        }
    
        public bool GetIsReady()        // return the status of json data loaded protcss.
        {
            return isReady;
        }
    
    }
    

    5、设置不同Button下通过LocalizationManager加载不同语言的JSON文件。
     打开LoadingScreen,在LoadingScreen下创建一个名为LocalizationManager的空物体,将LocalizationManager脚本附加到该物体上。
     

    附加脚本LocalizationManager

    选择EnBtn,在Button Component的OnClick()事件中添加一项,将刚刚创建的LocalizationManager物体拖拽到上面,设置LoadLocalizedText方法并设置文件名为localizedText_en.json(记得加后缀)。

      添加点击事件

    GeBtn也执行同样的操作,只是它的文件名为localizedText_de.json。
     然后我们就可以Ctrl+P来进行观察:
      点击不同button,查看Console Panel下是否有提示信息输出,如果没有,请检查你的代码、json文件的存放位置。

       Debug输出

    6、构建StartUpManger类
     为了防止点击按钮后,json文件还未加载完毕就加载场景,导致出现一些问题,我们应该对json文件的加载过程进行检测,只有加载完毕json文件后,才能进入MenuScreen。因此,在LocalizationManager类中我们使用了bool类型的isReady来标识当前json文件的加载是否完毕,并实现了读取isReady的接口,所以在StartUpManager中我们只需要检测isReady的状态便可决定是否Load到MenuScreen中。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class StartUpManager : MonoBehaviour {
    
        IEnumerator Start()
        {
            while (!LocalizationManager.instance.GetIsReady ()) {
                // Wait a frame.
                yield return null;
            }
    
            SceneManager.LoadScene ("MenuScreen");
        }
    
    }
    

    使用协程,如果JSON文件加载完毕,则让Start()等待一帧。
     在LoadingScreen中创建一个名为StartUpManager的空物体,并将StartUpManager脚本拖拽到上面,然后Ctrl+P,点击Button,看看是否成功加载到MenuScreen中。
     注意,请把LoadingScreen和MenuScreen都添加到BuildSettings中。
     
     7、构建LocalizedText实现不同UI对应不同文本
     在LocalizationManager中实现了GetLocalizedValue方法,设置不同的key来读取对应的值。
     LocalizedText:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class LocalizedText : MonoBehaviour {
    
        public string key;          // the key of UI.
    
        void Start()
        {
            Text text = GetComponent<Text> ();
            text.text = LocalizationManager.instance.GetLocalizedValue (key);   // set the ui's text
        }
    
    }
    

    将LocalizedText脚本附加到MenuScreen的Title Text和button的text中。

      附加脚本LocalizedText

    设置Title Text的LocalizedText 对应的key为game_titile;
     Text的LocalizedText 对应的key为start_button;


    设置game_title的key值
      设置start_button的key值

    8、完成所有逻辑!
     打开LoadingScreen Scene,Ctrl+P执行并进行调试,观察点击不同语言按钮后MenuScreen内UI的Text是否有转换为相对应的语言。
     注意,有时候Text的value太长,会导致只显示一部分的text,因此需要根据实际情况来对UI进行范围的调整。

    9、自定义编辑器
     如果开发的游戏比较大型,并且该游戏需要多语言支持的时候,我们需要翻译,但如果队伍里没有相应的翻译人员或者翻译人员不懂Unity的使用方法的话,翻译工作还是会显得很蛋疼。我们希望,翻译人员不需要懂得编程便可以对游戏进行翻译工作。通过自定义编辑器,我们可以实现新建、保存、和打开指定的JSON文件并进行方便直观的翻译工作。
     在Scripts文件夹下创建Editor文件夹,在Editor文件夹下新建C#文件LocalizedTextEditor。
     LocalizedTextEditor:

    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    
    public class LocalizedTextEditor : EditorWindow {
    
        public LocalizationData localizationData;       // The LocalizationData we current editing.
    
        [MenuItem("Window/Localized Text Editor")]      // we can show the localized text editor by select Window/Localized Text Editor
        static void Init()
        {
            EditorWindow.GetWindow (typeof(LocalizedTextEditor)).Show ();   // show the editor window.
        }
    
        void OnGUI()        // determine what the localized text editor window show. after open the editor, it will update editor per frame.
        {
            if (localizationData != null) {
                SerializedObject serializedObject = new SerializedObject (this);    // the window connect to this.
                SerializedProperty serializedProperty = serializedObject.FindProperty ("localizationData"); // get localizationData from this.
                EditorGUILayout.PropertyField (serializedProperty, true);   // set the localizationData can be fold
                serializedObject.ApplyModifiedProperties ();    // Apply these settings.
    
                if (GUILayout.Button ("Save data")) {       // Draw Save data Button to execute SaveGameData() logic.
                    SaveGameData ();
                }
            }
    
            if (GUILayout.Button ("Load data")) {           // Draw Load data Button to execute LoadGameData() logic.
                LoadGameData ();
            }
    
            if (GUILayout.Button ("Create new data")) {     // Draw Create new data to execute CreateNewData() logic.
                CreateNewData ();
            }
        }
    
        void LoadGameData()
        {
            string filePath = EditorUtility.OpenFilePanel ("Select localization data file", Application.streamingAssetsPath, "json");   // get the filePath of the json file selected by user.
    
            if (!string.IsNullOrEmpty (filePath)) {
                string dataAsJson = File.ReadAllText (filePath);        // read all data from json.
                localizationData = JsonUtility.FromJson<LocalizationData> (dataAsJson);     // store json data into localizationData.
            }
        }
    
        void SaveGameData()
        {
            string filePath = EditorUtility.SaveFilePanel ("Save localization data file", Application.streamingAssetsPath, "", "json");     // set the save path of json file we just edited.
    
            if (!string.IsNullOrEmpty (filePath)) {
                string dataAsJson = JsonUtility.ToJson (localizationData);      // Transform the localizationData to string 
                File.WriteAllText (filePath, dataAsJson);           // store the data into json file.
            }
        }
    
        void CreateNewData()                    
        {   
            localizationData = new LocalizationData ();         // create a new localizationData instance.
        }
    
    }
    

    Editor Window的更多详情可查看Documentation - Editor Window
     脚本编写完毕便可打开Localized Text Editor来体验它的方便之处了~
     

    打开Localized Text Editor 编辑配置文件

    很多时候,编写不同的Unity工具可以提高团队开发效率,这个小技巧不仅仅是适用于当前的案例,就像最近Unity3d官方发布的2D Game Kits,让用户可以根据自己的喜好制作一款横版2d闯关游戏,而不需要关注太多的编码细节。

    以上,完毕!

    相关文章

      网友评论

        本文标题:【案例】Unity3d官方案例之Localization Too

        本文链接:https://www.haomeiwen.com/subject/ztpnlftx.html