UnityUGUI本地化⽅案-LocaliztionTool
问题及难点
相信做海外游戏代理的同学⼀定会遇到需要做本地化的问题,其中资源可以通过替换合图来处理。⽽⽂本是其中⼀个⽐较难处理的问题。其中主要难点在于UGUI本⾝没有提供相应的插件,⽽对于⼀开始没规划的项⽬来说,你需要去找出其中所有的外语⽂本,找到后再将对
应Text控件替换成你⾃定义的控件,替换后再需要填⼊对应的Key值。这对于策划来说简直是恶梦~
⼯具的基本原理
LocalizationText控件
UGUI中的Text控件只提供了text属性接⼝供你进⾏对⽂本的设置,那么要实现本地化有下⾯两种做法:
1.在Text控件初始化后使⽤代码将其text属性修改,这样的话,我们需要在所有的有Text控件的地⽅添加相应的修改代码,这显然是
不符合可持续发展的。
2.⾃定义新的Text控件,在编辑器阶段完成对Key值的设置。这种⽅案需要我们继承Text控件,并修改其输⼊接⼝,从修改text改为修
改Key,通过Key来得到相应语⾔的⽂本。
综上,我们采取第⼆种⽅案来实现我们的LocalizationText控件,通过对Key的设置得到⽂本,如图:
有了LocaliztionText我们只需要输⼊Key**Help**⽽不需要直接填写帮助⼆字,通过为不同语⾔建⽴映射表我们就可得到对应语⾔的Help的⽂
本。
相关代码实现
这⾥我主要是先去看了,根据其中Text的实现做了修改。
using System;
using UnityEngine.UI;
using UnityEngine;
namespace Localization
{
public class LocalizationText : Text
{
#region Param
[Header("Localization")]
[SerializeField]
protected string m_KeyString;
public string keyString {
get {return this.m_KeyString; }
t { this.m_KeyString = value; }
}
扑扑超市快送#endregion
#region Override Part
public override string text
{
get
{
if (!ClientString.LocalizationDict.ContainsKey(keyString))
{
m_Text = string.Format("[{0}]",m_KeyString);
}
实施乡村振兴战略el
{
m_Text = ClientString.LocalizationDict[keyString];
}
return m_Text;
}住宅楼层风水
t便利店市场分析
{
if (String.IsNullOrEmpty(value))
{
心灵鸡汤正能量短文if (String.IsNullOrEmpty(m_Text))
return;
m_Text = "";
SetVerticesDirty();
}
el if (m_Text != value)
{
m_Text = value;
SetVerticesDirty();
SetLayoutDirty();
}
}
面包烘焙}
#endregion
}
}
这部分的代码其实⽐较简单,主要是进⾏了⼀个Key/Value的映射,然后设置对应的Text。其中的KeyString则是多语⾔⽂本映射⽤的Key 值。
总的来说,此控件的原理是⽐较简单的,Key->Value->Set Text。但对于⼀个完整的⽅案来说这是远远不够的,我们还需要有⾃动化修改的⼯具。
控件替换⼯具
这个⼯具简直是那些⽤UGUI的Text控件开发了很久后,突然想做多语⾔的项⽬的救星。因为如果你通
过将项⽬中的Text控件删除后再AddComponent< LocalizationText >的话会出现⼀个很灾难性的问题,那就是MonoBehaviour中对相应Text控件的引⽤都会丢失,因为Unity是通过GUID和FileID来找到对应类型控件的,⽽这样的处理⽅式会让GUID和FileID改变从⽽导致严重的后果。所以这个控件替换⼯具就⾮常重要了~
原理
上⾯说到Unity中⽤GUID和FileID来找对应类型控件的,那么只需要找到初始Text控件的GUID和FileID,然后更改为LocaliztionText控件的GUID和FileID则可以达到我们的⽬的。下⾯是⼀个场景⽂件(.unity)⽂件的内容,我们在场景⽂件中添加了⼀个物体名叫Normal Text上⾯挂着Text控件。
中间的图⽚表⽰的是Normal Text这个物体的结构,他有三个m_Component其中有⼀个是Text,Text控件的结构如图,所以在右边Text Component部分的m_Script处,只要把FileID和GUID修改为Localization Text对应的FileID和GUID即可,这样就避免了上⾯提到的引⽤丢失问题。那么怎么得到Localiztion Text的GUID和FileID呢。最简单的⽅法是添加⼀个Localization Text物体(也就是现在场景中的Localization Text),然后去场景⽂件内容中查看。
所以此⼯具的基本原理就是将Text控件的FileID和GUID换成LocaliztionText控件的FileID和GUID。
底薪怎么算具体代码如下(基本就是⼀个⽂本级别的操作):
public static void UpgradeToLocalizationText(string astPath, string textCompGUID, string textCompFileID, string localizeCompGUID, string localizeComp {
ClearConsole();
string formatedGUID = string.Format("guid: {0},", localizeCompGUID);
string fullPath = Path.Combine(Application.dataPath.Substring(0, Application.dataPath.LastIndexOf('/')), astPath);
string[] lines = System.IO.File.ReadAllLines(fullPath);
string fullText = System.IO.File.ReadAllText(fullPath);
for (int i = 0; i < lines.Length; i++)
咳嗽可以吃鱼吗{
if(lines[i].Contains(textCompFileID)) {
int scriptLineIdx = i; //往下遍历直到找到m_Text
while(i < lines.Length) {
if(lines[i].Contains("--- !u!")) //发现下⼀个控件时跳出
break;
if (JpUtil.PlainText_IsContainsJapane(lines[i]))
{
string jpText = Regex.Unescape(lines[i].Split('\"')[1]).Replace("\n", "\\n");
jpTextList.Add(jpText);
//发现了FileID相同但GUID不同的情况,所以直接把FileID后⾯的GUID替换
lines[scriptLineIdx] = Regex.Replace(lines[scriptLineIdx], guidReplacePattern, formatedGUID);
lines[scriptLineIdx] = lines[scriptLineIdx].Replace(textCompFileID, localizeCompFileID);
break;
}
i++;
}
}
}
string text = string.Join("\n", lines);
System.IO.File.WriteAllText(fullPath, text);
AstDataba.Refresh();
}
优化⽅案
上⾯的控件及⼯具解决了这⼀⽅案中的两个难点,但是我们还可以进⾏优化,就是对有需要变化(例如内容为⽇⽂或者英⽂)的控件才进⾏
转化,这其中的处理就是
JpUtil.PlainText_IsContainsJapane(lines[i])
这⼀处理会判断⽂本中是否有⽇⽂,有的话才对Text控件进⾏升级,所以你需要为不同的语⾔做不同的⽂本判断,我们项⽬为⽇⽂所以我做
了⽇⽂的判断。
除此之外在策划将对应的翻译都处理好后需要来设置LocaliztionText的Key值,我新增了⼀个⾃动设置Key值的功能,原理是将其中的内容进
⾏⽐对,⽤Value找到Key值,然后填⼊。
这个⼯具已经上传到GitHub: (⿇烦Star⼀哈)