赞
踩
文章目录
开发超休闲小游戏时,由于大部分游戏都是出海发布的,所以需要支持多语言。
目前运用比较广泛的本地化插件为I2 Localization。不过该插件功能繁杂,于是编写了一个简易版的语言本地化功能。
项目开发过程中,将数据存放在Excel中方便查看也方便更改。然后通过读取Excel的内容,将其表中内容读取到项目中对应的class实例(LocalizationData)中,然后将该实例生成一个Asset,如图所示:
生成好之后,我们就可以在游戏中通过这个Asset来获取我们需要的数据啦~
第一个枚举:语言类型。
- //这里保证与Excel表顺序一致
- public enum LanguageType
- {
- English = 0,//默认语言类型为英文
- Chinese = 1
- }
第二个枚举:需要进行本地化的文本类型Key。
- public enum TextKey
- {
- Racing_Bricks,
- Score,
- High_Score,
- Speed,
- Quick,
- Down,
- Left,
- Right,
- Rotate_Direction
- }
第一个类:用来存放每行的单元格表数据。
- using System;
- using UnityEngine;
-
- namespace SmipleLocalization
- {
- [Serializable]
- public class ItemData
- {
- [SerializeField]
- private string itemName;//语言名称,主要是方便编辑器上查看
- public LanguageType languageType;//语言类型
- public string content;//对应的内容
-
- //构造函数:初始化数据成员
- public ItemData(LanguageType _languageType, string _content)
- {
- this.languageType = _languageType;
- this.itemName = _languageType.ToString();
- this.content = _content;
- }
- }
- }
第二个类:用来存放前者的数组即每行的表数据。
- using System;
- using System.Collections.Generic;
- using UnityEngine;
-
- namespace SmipleLocalization
- {
- [Serializable]
- public class TextLocalization
- {
- [SerializeField]
- private string keyName;//当前文本类型名称,主要是方便编辑器上查看
- public TextKey curTextKey;//该文本类型
- public List<ItemData> itemDatas = new List<ItemData>();//当前文本类型对应的语言本地化文本信息
-
- //构造函数:初始化
- public TextLocalization(string _textKey, params string[] language)
- {
- this.keyName = _textKey;
- this.curTextKey = (TextKey)Enum.Parse(typeof(TextKey), _textKey);
- for (int i = 0; i < language.Length; i++)
- {
- ItemData cnData = new ItemData((LanguageType)i, language[i]);
- itemDatas.Add(cnData);
- }
- }
-
- //根据语言类型查找对应语言文本信息
- public ItemData GetType(LanguageType t)
- {
- for (int i = 0; i < this.itemDatas.Count; i++)
- {
- if (this.itemDatas[i].languageType == t)
- {
- return this.itemDatas[i];
- }
- }
- throw new KeyNotFoundException("Language not found: " + t);
- }
- }
- }
-
第三个类:用来存放第二个类的数组即所有的表数据。
- using UnityEngine;
- using System;
- using System.Collections.Generic;
-
-
- namespace SmipleLocalization
- {
- public class LocalizationData : ScriptableObject
- {
- public List<TextLocalization> localizationTxts = new List<TextLocalization>();
-
- /// <summary>
- /// 根据TextKey获取对应的所有语言类型信息
- /// </summary>
- /// <param name="k">需要本地化的文本</param>
- public TextLocalization GetTextInfo(TextKey k)
- {
- for (int i = 0; i < this.localizationTxts.Count; i++)
- {
- if (this.localizationTxts[i].curTextKey == k)
- {
- return this.localizationTxts[i];
- }
- }
- //return null;
- throw new KeyNotFoundException("TextKey not found: " + k);
- }
- }
-
- }
-
下载地址:Unity读取和写入Excel表格所需dll-Unity3D文档类资源-CSDN文库
1.定义一个类,里面存放我们需要的字段:
- using UnityEngine;
-
- namespace SmipleLocalization
- {
- public class LocalizationExcelConfig : MonoBehaviour
- {
- /// <summary>
- /// 存放将Excel表格数据转化CS文件的文件夹路径
- /// </summary>
- public static readonly string assetFolderPath = "Assets/Resources/Datas/";
-
- /// <summary>
- /// 存放将Excel表格数据转化CS文件的路径
- /// </summary>
- public static readonly string assetPath = string.Format("{0}{1}.asset", assetFolderPath, "LanguageLocalizationData");
-
- /// <summary>
- /// 加载文件的路径
- /// </summary>
- public static readonly string loadAssetPath = "Datas/LanguageLocalizationData";
- }
- }
-
2.定义一个类,用来读取Excel表格的数据,并解析数据存放到Asset中
- using System.Collections.Generic;
- using System.Data;
- using System.IO;
- using Excel;
-
- namespace SmipleLocalization
- {
- public class LocalizationExcelTool
- {
- /// <summary>
- /// 读取表格数据,生成对应的数据
- /// </summary>
- public static List<TextLocalization> CreateDataWithExcel(string filePath)
- {
- List<TextLocalization> localizationTxts = new List<TextLocalization>();
- //获得表格数据
- int row = 0, column = 0;
- DataRowCollection collection = ReadExcel(filePath, ref row, ref column);
- //根据Excel表的定义,第二行开始才是数据
- for (int i = 1; i < row; i++)
- {
- string[] language = new string[column - 1];
- for (int j = 1; j < column; j++)
- {
- language[j - 1] = collection[i][j].ToString();
- }
- TextLocalization tl = new TextLocalization(collection[i][0].ToString(), language);
- localizationTxts.Add(tl);
- }
- return localizationTxts;
- }
-
- /// <summary>
- /// 读取Excel文件内容
- /// </summary>
- /// <param name="filePath">文件路径</param>
- /// <param name="row">行数</param>
- /// <param name="column">列数</param>
- private static DataRowCollection ReadExcel(string filePath, ref int row, ref int column)
- {
- FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
- IExcelDataReader edReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
-
- DataSet result = edReader.AsDataSet();
- //Tables[0]下标0表示Excel文件中第一张表的数据
- row = result.Tables[0].Rows.Count;
- column = result.Tables[0].Columns.Count;
- return result.Tables[0].Rows;
- }
- }
- }
3.将拿到的数据存放在LocalizationData中,并生成一个Asset文件:
- using System.IO;
- using UnityEditor;
- using UnityEngine;
-
- namespace SmipleLocalization
- {
- public class BuildExcelDataEditor : Editor
- {
- [MenuItem("CustomEditor/CreateLocalizationData")]
- public static void CreateLocalizationData()
- {
- //打开Excel
- string filePath = EditorUtility.OpenFilePanel("Open Localization Excel", "", "xlsx");
- //获取Excel数据
- LocalizationData data = ScriptableObject.CreateInstance<LocalizationData>();
- data.localizationTxts = LocalizationExcelTool.CreateDataWithExcel(filePath);
- //判断文件夹是否存在
- if (!Directory.Exists(LocalizationExcelConfig.assetFolderPath))
- {
- Directory.CreateDirectory(LocalizationExcelConfig.assetFolderPath);
- }
- string assetPath = LocalizationExcelConfig.assetPath;
- //判断文件是否已经存在
- //若已经存在,则删除该文件
- if (File.Exists(assetPath))
- {
- AssetDatabase.DeleteAsset(assetPath);
- }
- //生成一个Asset文件
- AssetDatabase.CreateAsset(data, assetPath);
- AssetDatabase.SaveAssets();
- AssetDatabase.Refresh();
- }
- }
- }
这样我们就可以在Unity中选择我们自定义的菜单CustromEditor->CreateLocalizationData,然后选择我们需要的Excel表格,即可生成Asset了。
- using UnityEngine;
- using System;
-
- namespace SmipleLocalization
- {
- public static class LocalizationSys
- {
- private static LocalizationData localizationDatas;
- public static Action ChangeCurLanguageTypeEvent;//监听语言类型变化事件,在事件触发时设置内容,主要是方便用来游戏运行中测试本地化
- private static LanguageType mCurLanguageType;
-
- static LocalizationSys()
- {
- InitDatas();
- InitLanguageType();
- }
-
- /// <summary>
- /// 加载数据
- /// </summary>
- private static void InitDatas()
- {
- localizationDatas = Resources.Load<LocalizationData>(LocalizationExcelConfig.loadAssetPath);
- }
-
- /// <summary>
- /// 根据系统语言设置默认语言
- /// </summary>
- private static void InitLanguageType()
- {
- SystemLanguage languageStr = Application.systemLanguage;
- if (languageStr == SystemLanguage.Chinese ||
- languageStr == SystemLanguage.ChineseSimplified)
- {
- CurLanguageType = LanguageType.Chinese;
- }
- else
- {
- CurLanguageType = LanguageType.English;
- }
- }
-
- /// <summary>
- /// 设置当前语言类型
- /// </summary>
- public static LanguageType CurLanguageType
- {
- set
- {
- if (mCurLanguageType != value)
- {
- mCurLanguageType = value;
- ChangeCurLanguageTypeEvent?.Invoke();
- }
- }
- }
-
- /// <summary>
- /// 对应的语言本地化
- /// </summary>
- /// <param name="textKey">需要本地化的文本</param>
- public static string Localize(TextKey textKey)
- {
- return Localize(textKey, mCurLanguageType);
- }
-
- /// <summary>
- /// 获取对应的语言本地化
- /// </summary>
- /// <param name="textKey">需要本地化的文本</param>
- /// <param name="languageType">语言类型</param>
- /// <returns></returns>
- private static string Localize(TextKey textKey, LanguageType languageType)
- {
- string value = string.Empty;
- TextLocalization textInfo = localizationDatas.GetTextInfo(textKey);
- if (textInfo != null)
- {
- ItemData typeInfo = textInfo.GetType(languageType);
- //如果没找到对应语言本地化信息,则设置默认英文信息
- if (typeInfo == null)
- {
- typeInfo = textInfo.GetType(LanguageType.English);
- }
- value = typeInfo.content;
- }
- return value;
- }
- }
-
- //这里保证与Excel表顺序一致
- public enum LanguageType
- {
- English = 0,//默认语言类型为英文
- Chinese = 1
- }
-
- public enum TextKey
- {
- Racing_Bricks,
- Score,
- High_Score,
- Speed,
- Quick,
- Down,
- Left,
- Right,
- Rotate_Direction
- }
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
- namespace SmipleLocalization
- {
- public class UITextLocalize : MonoBehaviour
- {
- private Text mText;
- [SerializeField]
- private TextKey textKey;
-
- private void Awake()
- {
- this.mText = base.GetComponent<Text>();
- }
-
- private void Start()
- {
- LocalizationSys.ChangeCurLanguageTypeEvent += OnChangeLanguage;
- this.OnChangeLanguage();
- }
-
- private void OnDestroy()
- {
- LocalizationSys.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
- }
-
- private void OnChangeLanguage()
- {
- this.StaticSet();
- }
-
- private void StaticSet()
- {
- this.mText.text = LocalizationSys.Localize(textKey);
- }
- }
- }
- public void OnChangeLanguage(int value)
- {
- LocalizationSys.CurLanguageType = (LanguageType)value;
- }
这样我们就可以在游戏运行中查看我们的多语言本地化是否正确了。
这款游戏中我只用到了静态文本,但是有时候我们还需要简单的动态修改文本内容。这个时候我们修改一下UITextLocalize脚本即可,如下:
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
- namespace SmipleLocalization
- {
- public class UITextLocalize : MonoBehaviour
- {
- private Text mText;
- [SerializeField]
- private TextKey textKey;
- [SerializeField]
- private LocalizeType localizeType = LocalizeType.Static;
- private object[] args;
- private void Awake()
- {
- this.mText = base.GetComponent<Text>();
- }
-
- private void Start()
- {
- LocalizationSys.ChangeCurLanguageTypeEvent += OnChangeLanguage;
- this.OnChangeLanguage();
- }
-
- private void OnDestroy()
- {
- LocalizationSys.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
- }
-
- private void OnChangeLanguage()
- {
- if (this.localizeType == LocalizeType.Static)
- {
- this.StaticSet();
- }
- else if(this.args != null)
- {
- this.DynamicSet(this.args);
- }
- }
-
- private void StaticSet()
- {
- this.mText.text = LocalizationSys.Localize(textKey);
- }
-
- /// <summary>
- /// 动态设置文本内容
- /// </summary>
- public void DynamicSet(params object[] _args)
- {
- string format = LocalizationSys.Localize(textKey);
- this.mText.text = string.Format(format, _args);
- this.args = _args;
- }
- }
- }
然后在Inspector面板上设置UITextLocalize的LocalizeType为Dynamic。
接着在需要动态修改Text内容时,不是调用GetComponent<Text>().text去设置,而是调用GetComponent<UITextLocalize>().DynamicSet(),传入需要修改的数据即可。参考如下:
大家也可以试试导入EPPlus.dll,用来向Excel写入数据。后续会给大家整理一下。今天就到这里啦~
以上就是今天要讲的内容,如果有哪里不懂的可以留言交流一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。