当前位置:   article > 正文

【Unity功能实现】SmipleLocalization多语言本地化简易版本_unity 本地化 方案

unity 本地化 方案

文章目录

前言

一、基本功能介绍

二、功能详解

1.创建Excel表格,确定所需数据

2.读取Excel表格

3.处理Unity中需要本地化的Text

三、扩展功能

总结


前言

开发超休闲小游戏时,由于大部分游戏都是出海发布的,所以需要支持多语言。

目前运用比较广泛的本地化插件为I2 Localization。不过该插件功能繁杂,于是编写了一个简易版的语言本地化功能。


一、基本功能介绍

项目开发过程中,将数据存放在Excel中方便查看也方便更改。然后通过读取Excel的内容,将其表中内容读取到项目中对应的class实例(LocalizationData)中,然后将该实例生成一个Asset,如图所示:

生成好之后,我们就可以在游戏中通过这个Asset来获取我们需要的数据啦~

二、功能详解

1.创建Excel表格,确定所需数据

  • 首先我们需要知道自己需要哪些数据。这里以我开发的俄罗斯方块案例来说明吧,游戏界面如下:

  • 创建Excel表格,填写数据信息,如图所示:

  • 根据Excel表格,我们需要定义两个枚举。

        第一个枚举:语言类型。

  1. //这里保证与Excel表顺序一致
  2. public enum LanguageType
  3. {
  4. English = 0,//默认语言类型为英文
  5. Chinese = 1
  6. }

        第二个枚举:需要进行本地化的文本类型Key。

  1. public enum TextKey
  2. {
  3. Racing_Bricks,
  4. Score,
  5. High_Score,
  6. Speed,
  7. Quick,
  8. Down,
  9. Left,
  10. Right,
  11. Rotate_Direction
  12. }
  • 根据Excel表格,定义三个基础类。

        第一个类:用来存放每行的单元格表数据。

  1. using System;
  2. using UnityEngine;
  3. namespace SmipleLocalization
  4. {
  5. [Serializable]
  6. public class ItemData
  7. {
  8. [SerializeField]
  9. private string itemName;//语言名称,主要是方便编辑器上查看
  10. public LanguageType languageType;//语言类型
  11. public string content;//对应的内容
  12. //构造函数:初始化数据成员
  13. public ItemData(LanguageType _languageType, string _content)
  14. {
  15. this.languageType = _languageType;
  16. this.itemName = _languageType.ToString();
  17. this.content = _content;
  18. }
  19. }
  20. }

        第二个类:用来存放前者的数组即每行的表数据。

  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace SmipleLocalization
  5. {
  6. [Serializable]
  7. public class TextLocalization
  8. {
  9. [SerializeField]
  10. private string keyName;//当前文本类型名称,主要是方便编辑器上查看
  11. public TextKey curTextKey;//该文本类型
  12. public List<ItemData> itemDatas = new List<ItemData>();//当前文本类型对应的语言本地化文本信息
  13. //构造函数:初始化
  14. public TextLocalization(string _textKey, params string[] language)
  15. {
  16. this.keyName = _textKey;
  17. this.curTextKey = (TextKey)Enum.Parse(typeof(TextKey), _textKey);
  18. for (int i = 0; i < language.Length; i++)
  19. {
  20. ItemData cnData = new ItemData((LanguageType)i, language[i]);
  21. itemDatas.Add(cnData);
  22. }
  23. }
  24. //根据语言类型查找对应语言文本信息
  25. public ItemData GetType(LanguageType t)
  26. {
  27. for (int i = 0; i < this.itemDatas.Count; i++)
  28. {
  29. if (this.itemDatas[i].languageType == t)
  30. {
  31. return this.itemDatas[i];
  32. }
  33. }
  34. throw new KeyNotFoundException("Language not found: " + t);
  35. }
  36. }
  37. }

        第三个类:用来存放第二个类的数组即所有的表数据。

  1. using UnityEngine;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace SmipleLocalization
  5. {
  6. public class LocalizationData : ScriptableObject
  7. {
  8. public List<TextLocalization> localizationTxts = new List<TextLocalization>();
  9. /// <summary>
  10. /// 根据TextKey获取对应的所有语言类型信息
  11. /// </summary>
  12. /// <param name="k">需要本地化的文本</param>
  13. public TextLocalization GetTextInfo(TextKey k)
  14. {
  15. for (int i = 0; i < this.localizationTxts.Count; i++)
  16. {
  17. if (this.localizationTxts[i].curTextKey == k)
  18. {
  19. return this.localizationTxts[i];
  20. }
  21. }
  22. //return null;
  23. throw new KeyNotFoundException("TextKey not found: " + k);
  24. }
  25. }
  26. }

2.读取Excel表格

  • 需要引入Excel.dll和ICSharpCode.SharpZipLib库文件,放到Plugins文件夹下。

        下载地址:Unity读取和写入Excel表格所需dll-Unity3D文档类资源-CSDN文库

  • 在Editor文件夹下创建cs文件去实现读取Excel操作。       

        1.定义一个类,里面存放我们需要的字段:

  1. using UnityEngine;
  2. namespace SmipleLocalization
  3. {
  4. public class LocalizationExcelConfig : MonoBehaviour
  5. {
  6. /// <summary>
  7. /// 存放将Excel表格数据转化CS文件的文件夹路径
  8. /// </summary>
  9. public static readonly string assetFolderPath = "Assets/Resources/Datas/";
  10. /// <summary>
  11. /// 存放将Excel表格数据转化CS文件的路径
  12. /// </summary>
  13. public static readonly string assetPath = string.Format("{0}{1}.asset", assetFolderPath, "LanguageLocalizationData");
  14. /// <summary>
  15. /// 加载文件的路径
  16. /// </summary>
  17. public static readonly string loadAssetPath = "Datas/LanguageLocalizationData";
  18. }
  19. }

        2.定义一个类,用来读取Excel表格的数据,并解析数据存放到Asset中

  1. using System.Collections.Generic;
  2. using System.Data;
  3. using System.IO;
  4. using Excel;
  5. namespace SmipleLocalization
  6. {
  7. public class LocalizationExcelTool
  8. {
  9. /// <summary>
  10. /// 读取表格数据,生成对应的数据
  11. /// </summary>
  12. public static List<TextLocalization> CreateDataWithExcel(string filePath)
  13. {
  14. List<TextLocalization> localizationTxts = new List<TextLocalization>();
  15. //获得表格数据
  16. int row = 0, column = 0;
  17. DataRowCollection collection = ReadExcel(filePath, ref row, ref column);
  18. //根据Excel表的定义,第二行开始才是数据
  19. for (int i = 1; i < row; i++)
  20. {
  21. string[] language = new string[column - 1];
  22. for (int j = 1; j < column; j++)
  23. {
  24. language[j - 1] = collection[i][j].ToString();
  25. }
  26. TextLocalization tl = new TextLocalization(collection[i][0].ToString(), language);
  27. localizationTxts.Add(tl);
  28. }
  29. return localizationTxts;
  30. }
  31. /// <summary>
  32. /// 读取Excel文件内容
  33. /// </summary>
  34. /// <param name="filePath">文件路径</param>
  35. /// <param name="row">行数</param>
  36. /// <param name="column">列数</param>
  37. private static DataRowCollection ReadExcel(string filePath, ref int row, ref int column)
  38. {
  39. FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
  40. IExcelDataReader edReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
  41. DataSet result = edReader.AsDataSet();
  42. //Tables[0]下标0表示Excel文件中第一张表的数据
  43. row = result.Tables[0].Rows.Count;
  44. column = result.Tables[0].Columns.Count;
  45. return result.Tables[0].Rows;
  46. }
  47. }
  48. }

        3.将拿到的数据存放在LocalizationData中,并生成一个Asset文件:

  1. using System.IO;
  2. using UnityEditor;
  3. using UnityEngine;
  4. namespace SmipleLocalization
  5. {
  6. public class BuildExcelDataEditor : Editor
  7. {
  8. [MenuItem("CustomEditor/CreateLocalizationData")]
  9. public static void CreateLocalizationData()
  10. {
  11. //打开Excel
  12. string filePath = EditorUtility.OpenFilePanel("Open Localization Excel", "", "xlsx");
  13. //获取Excel数据
  14. LocalizationData data = ScriptableObject.CreateInstance<LocalizationData>();
  15. data.localizationTxts = LocalizationExcelTool.CreateDataWithExcel(filePath);
  16. //判断文件夹是否存在
  17. if (!Directory.Exists(LocalizationExcelConfig.assetFolderPath))
  18. {
  19. Directory.CreateDirectory(LocalizationExcelConfig.assetFolderPath);
  20. }
  21. string assetPath = LocalizationExcelConfig.assetPath;
  22. //判断文件是否已经存在
  23. //若已经存在,则删除该文件
  24. if (File.Exists(assetPath))
  25. {
  26. AssetDatabase.DeleteAsset(assetPath);
  27. }
  28. //生成一个Asset文件
  29. AssetDatabase.CreateAsset(data, assetPath);
  30. AssetDatabase.SaveAssets();
  31. AssetDatabase.Refresh();
  32. }
  33. }
  34. }

        这样我们就可以在Unity中选择我们自定义的菜单CustromEditor->CreateLocalizationData,然后选择我们需要的Excel表格,即可生成Asset了。

3.处理Unity中需要本地化的Text

  • 创建一个类,在游戏运行时,加载数据,为目标提供本地化方法
  1. using UnityEngine;
  2. using System;
  3. namespace SmipleLocalization
  4. {
  5. public static class LocalizationSys
  6. {
  7. private static LocalizationData localizationDatas;
  8. public static Action ChangeCurLanguageTypeEvent;//监听语言类型变化事件,在事件触发时设置内容,主要是方便用来游戏运行中测试本地化
  9. private static LanguageType mCurLanguageType;
  10. static LocalizationSys()
  11. {
  12. InitDatas();
  13. InitLanguageType();
  14. }
  15. /// <summary>
  16. /// 加载数据
  17. /// </summary>
  18. private static void InitDatas()
  19. {
  20. localizationDatas = Resources.Load<LocalizationData>(LocalizationExcelConfig.loadAssetPath);
  21. }
  22. /// <summary>
  23. /// 根据系统语言设置默认语言
  24. /// </summary>
  25. private static void InitLanguageType()
  26. {
  27. SystemLanguage languageStr = Application.systemLanguage;
  28. if (languageStr == SystemLanguage.Chinese ||
  29. languageStr == SystemLanguage.ChineseSimplified)
  30. {
  31. CurLanguageType = LanguageType.Chinese;
  32. }
  33. else
  34. {
  35. CurLanguageType = LanguageType.English;
  36. }
  37. }
  38. /// <summary>
  39. /// 设置当前语言类型
  40. /// </summary>
  41. public static LanguageType CurLanguageType
  42. {
  43. set
  44. {
  45. if (mCurLanguageType != value)
  46. {
  47. mCurLanguageType = value;
  48. ChangeCurLanguageTypeEvent?.Invoke();
  49. }
  50. }
  51. }
  52. /// <summary>
  53. /// 对应的语言本地化
  54. /// </summary>
  55. /// <param name="textKey">需要本地化的文本</param>
  56. public static string Localize(TextKey textKey)
  57. {
  58. return Localize(textKey, mCurLanguageType);
  59. }
  60. /// <summary>
  61. /// 获取对应的语言本地化
  62. /// </summary>
  63. /// <param name="textKey">需要本地化的文本</param>
  64. /// <param name="languageType">语言类型</param>
  65. /// <returns></returns>
  66. private static string Localize(TextKey textKey, LanguageType languageType)
  67. {
  68. string value = string.Empty;
  69. TextLocalization textInfo = localizationDatas.GetTextInfo(textKey);
  70. if (textInfo != null)
  71. {
  72. ItemData typeInfo = textInfo.GetType(languageType);
  73. //如果没找到对应语言本地化信息,则设置默认英文信息
  74. if (typeInfo == null)
  75. {
  76. typeInfo = textInfo.GetType(LanguageType.English);
  77. }
  78. value = typeInfo.content;
  79. }
  80. return value;
  81. }
  82. }
  83. //这里保证与Excel表顺序一致
  84. public enum LanguageType
  85. {
  86. English = 0,//默认语言类型为英文
  87. Chinese = 1
  88. }
  89. public enum TextKey
  90. {
  91. Racing_Bricks,
  92. Score,
  93. High_Score,
  94. Speed,
  95. Quick,
  96. Down,
  97. Left,
  98. Right,
  99. Rotate_Direction
  100. }
  101. }
  • 创建一个类,用来设置文本文字内容
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. namespace SmipleLocalization
  6. {
  7. public class UITextLocalize : MonoBehaviour
  8. {
  9. private Text mText;
  10. [SerializeField]
  11. private TextKey textKey;
  12. private void Awake()
  13. {
  14. this.mText = base.GetComponent<Text>();
  15. }
  16. private void Start()
  17. {
  18. LocalizationSys.ChangeCurLanguageTypeEvent += OnChangeLanguage;
  19. this.OnChangeLanguage();
  20. }
  21. private void OnDestroy()
  22. {
  23. LocalizationSys.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
  24. }
  25. private void OnChangeLanguage()
  26. {
  27. this.StaticSet();
  28. }
  29. private void StaticSet()
  30. {
  31. this.mText.text = LocalizationSys.Localize(textKey);
  32. }
  33. }
  34. }
  • 在需要本地化的文本上挂上UITextLocalize脚本,并配置对应的信息,如下所示:

  • 如果我们需要在游戏中测试多语言功能,可以在画布下创建一个DropDown,设置Options,添加OnValueChanged事件,如下所示:
  1. public void OnChangeLanguage(int value)
  2. {
  3. LocalizationSys.CurLanguageType = (LanguageType)value;
  4. }

这样我们就可以在游戏运行中查看我们的多语言本地化是否正确了。

三、扩展功能

这款游戏中我只用到了静态文本,但是有时候我们还需要简单的动态修改文本内容。这个时候我们修改一下UITextLocalize脚本即可,如下:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. namespace SmipleLocalization
  6. {
  7. public class UITextLocalize : MonoBehaviour
  8. {
  9. private Text mText;
  10. [SerializeField]
  11. private TextKey textKey;
  12. [SerializeField]
  13. private LocalizeType localizeType = LocalizeType.Static;
  14. private object[] args;
  15. private void Awake()
  16. {
  17. this.mText = base.GetComponent<Text>();
  18. }
  19. private void Start()
  20. {
  21. LocalizationSys.ChangeCurLanguageTypeEvent += OnChangeLanguage;
  22. this.OnChangeLanguage();
  23. }
  24. private void OnDestroy()
  25. {
  26. LocalizationSys.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
  27. }
  28. private void OnChangeLanguage()
  29. {
  30. if (this.localizeType == LocalizeType.Static)
  31. {
  32. this.StaticSet();
  33. }
  34. else if(this.args != null)
  35. {
  36. this.DynamicSet(this.args);
  37. }
  38. }
  39. private void StaticSet()
  40. {
  41. this.mText.text = LocalizationSys.Localize(textKey);
  42. }
  43. /// <summary>
  44. /// 动态设置文本内容
  45. /// </summary>
  46. public void DynamicSet(params object[] _args)
  47. {
  48. string format = LocalizationSys.Localize(textKey);
  49. this.mText.text = string.Format(format, _args);
  50. this.args = _args;
  51. }
  52. }
  53. }

然后在Inspector面板上设置UITextLocalize的LocalizeType为Dynamic。

接着在需要动态修改Text内容时,不是调用GetComponent<Text>().text去设置,而是调用GetComponent<UITextLocalize>().DynamicSet(),传入需要修改的数据即可。参考如下:


总结

大家也可以试试导入EPPlus.dll,用来向Excel写入数据。后续会给大家整理一下。今天就到这里啦~

以上就是今天要讲的内容,如果有哪里不懂的可以留言交流一下。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/106780
推荐阅读
相关标签
  

闽ICP备14008679号