Unity多语言(基于ET框架)

Posted 萧寒大大

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity多语言(基于ET框架)相关的知识,希望对你有一定的参考价值。

1.介绍

1. 代码枚举加语言(编辑器加语言)

2.一张Excle表配置所有语言

3.静态文本加载(编辑模式下可根据key看到value,Default Language为value的语言和游戏中的Language不同

4.动态文本加载 

 

2.核心代码示例

 1.LocalizationService.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace ETModel

   
    public class LocalizationService : ScriptableObject
    
        #region static
        private static LocalizationService _instance;
        public static LocalizationService Instance
        
            get  return _instance ?? (_instance = Create()); 
        

        /// <summary>
        /// LocalizationService的asset文件
        /// </summary>
        /// <returns></returns>
        static LocalizationService Create()
        
            return Resources.Load<LocalizationService>("LocalizationService");
        

        #endregion

        #region event
        /// <summary>
        /// 语言改变事件
        /// </summary>
        public static Action OnLanguageChanged;
        #endregion

        #region properties

        /// <summary>
        /// 存储所有语言信息
        /// </summary>
        public Dictionary<long, string> Strings = new Dictionary<long, string>();      

        /// <summary>
        /// 默认显示静态文本语言
        /// </summary>
        [HideInInspector]
        public LanguageInfo DefaultLanguage;

        /// <summary>
        /// 当前语言
        /// </summary>
        [HideInInspector]
        private LanguageInfo _language = LanguageInfo.Chinese;
        public LanguageInfo Language
        
            get  return _language; 
            set
            
                if (!HasLanguage(value))
                
                    Debug.LogError("Invalid Language " + value);
                

                _language = value;

                RaiseLanguageChanged();

                SaveToPrefs();
            
        

        /// <summary>
        /// 所有支持的语言
        /// </summary>
        [SerializeField]
        public LanguageInfo[] Languages = LanguageInfo.All;
        #endregion

        #region LocalizationService       

        public void Init()
        
            LoadLanguage();

#if UNITY_EDITOR
            if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
            
                return;
            
#endif
         //   ReadFiles();
        

        /// <summary>
        /// 默认加载语言
        /// </summary>
        void LoadLanguage()
        
            var raw = PlayerPrefs.GetString("CurrentLanguage");
            if (string.IsNullOrEmpty(raw))
            
                bool hasLan = false;
                for (int i = 0; i < Languages.Length; i++)
                
                    if (Application.systemLanguage == Languages[i].lan)
                    
                        hasLan = true;
                        Language = Languages[i];
                        break;
                    
                
                if (!hasLan)
                
                    Language = LanguageInfo.Chinese;
                
                return;
            


            var lan = Languages.FirstOrDefault(o => o.Name == raw);
            if (lan == null)
            
                Debug.LogError("Unknown language saved to prefs : " + raw);
                Language = LanguageInfo.Chinese;
            
            else
            
                Language = lan;
            
        

        /// <summary>
        /// 保存到本地
        /// </summary>
        void SaveToPrefs()
        
            PlayerPrefs.SetString("CurrentLanguage", Language.Name);
            PlayerPrefs.Save();
        

        #endregion

        #region internal

        /// <summary>
        /// 是否有配置该语言
        /// </summary>
        /// <param name="language"></param>
        /// <returns></returns>
        bool HasLanguage(LanguageInfo language)
        
            foreach (var systemLanguage in Languages)
            
                if (systemLanguage.Equals(language))
                    return true;
            
            return false;
        


        /// <summary>
        /// 切换语言
        /// </summary>
        private void RaiseLanguageChanged()
        
            
            if (Application.isPlaying)
            
                ReadFiles();
                if (OnLanguageChanged != null)
                    OnLanguageChanged();
            
        

        /// <summary>
        /// 读取当前语言配置(ET为例)
        /// </summary>
        void ReadFiles()
        
            Strings.Clear();

            var configs = Game.Scene.GetComponent<ConfigComponent>().GetAll(typeof(Localization));

            if (!configs.Any())
            
                Debug.LogError("Localization Files Not Found : " + Language.Name);
            


            foreach (Localization config in configs)
            
                ReadCSVAsset(config);
            
        

        /// <summary>
        /// 读取单条配置到缓存
        /// </summary>
        /// <param name="config"></param>
        void ReadCSVAsset(Localization config)
        
            try
            
                FieldInfo info = typeof(Localization).GetField(Language.Name);
                Strings.Add(config.Id, info.GetValue(config).ToString());

            
            catch (Exception ex)
            
                Debug.LogError(ex);
                Debug.LogError(string.Format("Failed to read file : 0/1  ", Language, config.Id));
            

        
        #endregion

        #region public

        /// <summary>
        /// 非运行模式下加载文本TODO
        /// </summary>
        public void LoadTextAssets()
        
            // ReadFiles();
#if UNITY_EDITOR
            Strings.Clear();
            var jsonObj = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Res/Config/Localization.txt", typeof(TextAsset)) as TextAsset;
            string[] jsonArray = jsonObj.text.Split('\\n');
            foreach (string tx in jsonArray)
            
                if (string.IsNullOrEmpty(tx))
                    continue;
                Localization json = JsonHelper.FromJson<Localization>(tx);
                FieldInfo info = typeof(Localization).GetField(DefaultLanguage.Name);
                Strings.Add(json.Id, info.GetValue(json).ToString());
                       
#endif
        

        /// <summary>
        /// 从字典获取多语言文本
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string Get(long key)
        
            return Get(key, string.Empty);
        

        /// <summary>
        /// 获取多语言文本,没有则返回默认值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="fallback"> if not found</param>
        /// <returns></returns>
        public string Get(long key, string fallback)
        
            if (!Strings.ContainsKey(key))
            
             //   Debug.LogWarning(string.Format("Localization Key Not Found 0 : 1 ", Language.Name, key));
                return fallback;
            

            return Strings[key];
        


        #endregion


    

2.LocalizationServiceEditor.cs

using ETModel;
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace ETEditor

    /// <summary>
    /// 绘制LocalizationService面板
    /// </summary>
    [CustomEditor(typeof(LocalizationService), true)]
    public class LocalizationServiceEditor : UnityEditor.Editor
    
        protected LocalizationService Target;

        
        [MenuItem("Tools/Foundation/Localization Service")]
        public static void ShowWindow()
        
            LocalizationInitializer.Startup();
            Selection.activeObject = LocalizationService.Instance;
            EditorGUIUtility.PingObject(LocalizationService.Instance);

        

        public override void OnInspectorGUI()
        
            base.OnInspectorGUI();

            LocalizationInitializer.Startup();

            Target = target as LocalizationService;

            if (Application.isPlaying)
                return;

            EditorGUILayout.LabelField("Default Language");
            var di = Array.IndexOf(Target.Languages, Target.DefaultLanguage);
            var di2 = EditorGUILayout.Popup(di, Target.Languages.Select(o => o.Name).ToArray());

            if (di != di2)
            
                Target.DefaultLanguage = Target.Languages[di2];
                Target.LoadTextAssets();
                EditorUtility.SetDirty(target);
            

            if (GUILayout.Button("Reset Language List"))
            
                Target.Languages = LanguageInfo.All;
                Debug.LogError(LanguageInfo.All[0].Name);
                Debug.LogError(LanguageInfo.All[1].Name);
                EditorUtility.SetDirty(target);
            
        
    

3.LocalizedText.cs

using UnityEngine;
using UnityEngine.UI;

namespace ETModel

    /// <summary>
    /// 静态文本
    /// </summary>
    [RequireComponent(typeof(Text))]
    [AddComponentMenu("Localization/LocalizedText")]
    public class LocalizedText : MonoBehaviour
    

        [HideInInspector]
        public long Key;

        private void Awake()
        
            OnLocalization();
            LocalizationService.OnLanguageChanged += OnLocalization;
        

        private void OnDestroy()
        
            LocalizationService.OnLanguageChanged -= OnLocalization;
        

        public void OnLocalization()
        
            var label = GetComponent<Text>();

            label.text = Game.Scene.GetComponent<LocaliztionComponent>().GetTextByKey(Key);
        

    

4.LocalizedTextEditor.cs

using ETModel;
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace ETEditor

    /// <summary>
    /// LocalizedText面板
    /// </summary>
    [CustomEditor(typeof(LocalizedText), true)]
    public class LocalizedTextEditor : UnityEditor.Editor
    
        protected LocalizedText Target;

        public override void OnInspectorGUI()
        
            base.OnInspectorGUI();

         //   LocalizationInitializer.Startup();

            Target = target as LocalizedText;

            if (Application.isPlaying)
                return;

            var service = LocalizationService.Instance;

            if (service != null)
            
                var p = EditorGUILayout.LongField("Key", Target.Key);

                if (p != Target.Key)
                
                    Target.Key = p;
                    EditorUtility.SetDirty(target);
                
                EditorGUILayout.LabelField("Value", service.Get(p));
            
           
        
    



5.LocaliztionComponent.cs

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


namespace ETModel

    [ObjectSystem]
    public class LocaliztionAwakeSystem : AwakeSystem<LocaliztionComponent>
    
        public override void Awake(LocaliztionComponent self)
        
            LocalizationService.Instance.Init();
        
    

    [ObjectSystem]
    public class LocaliztionDestroySystem : DestroySystem<LocaliztionComponent>
    
        public override void Destroy(LocaliztionComponent self)
        
            if (LocalizationService.Instance.Language != LocalizationService.Instance.DefaultLanguage)
                LocalizationService.Instance.LoadTextAssets();
        
    
    public class LocaliztionComponent : Component
    
        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetTextByKey(long key)
        
            return LocalizationService.Instance.Get(key);
        

        /// <summary>
        /// 切换语言
        /// </summary>
        /// <param name="info"></param>
        public void ChangeLanguage(LanguageInfo info)
        
            LocalizationService.Instance.Language = info;
        

        /// <summary>
        /// 动态文本如果切换语言时没有手动刷新界面的话,需要加上这个回调强制刷新
        /// </summary>
        /// <param name="act"></param>
        public void OnLanguageChanged(Action act)
        
            LocalizationService.OnLanguageChanged += act;
        
    


以上是关于Unity多语言(基于ET框架)的主要内容,如果未能解决你的问题,请参考以下文章

[Unity] 多语言字体的坑

Unity3D研究之多语言用中文做KEY

在WinForm应用程序中快速实现多语言的处理--开发框架模块的整合

ET介绍——强大的基于.dotnet7+Unity3d的双端C#开源游戏框架

Unity 本地化(多语言)插件Localization

Unity发布Windows平台exe后制作成漂亮美观的Setup.exe安装程序(图文讲解,支持多语言,含Demo源码)