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框架)的主要内容,如果未能解决你的问题,请参考以下文章
在WinForm应用程序中快速实现多语言的处理--开发框架模块的整合
ET介绍——强大的基于.dotnet7+Unity3d的双端C#开源游戏框架
Unity发布Windows平台exe后制作成漂亮美观的Setup.exe安装程序(图文讲解,支持多语言,含Demo源码)