UGUI 文本多语言方案
- 作者:admin
- /
- 时间:2018年10月16日
- /
- 浏览:8278 次
- /
- 分类:厚积薄发
前言
为了使全世界的玩家都能自由流畅的玩到游戏,游戏支持多国语言是一个常见的需求。游戏的多语言涉及到UI显示,声音,图片等等,而UI中文本的多语言处理是基础。
Unity引擎主流的两套UI框架中,NGUI默认实现了UI文本的多语言功能,而UGUI并没有原生实现。导致我们的项目从NGUI迁移到UGUI的过程中遇到了麻烦,本文介绍了目前UGUI框架下文本多语言的几种方案,以及我们的实现。
我们的需求
1.参考NGUI,使用一套key对应多套文本的方式,来实现多语言。
2.支持游戏内动态切换语言,切换语言后自动刷新UI显示。
3.使用简单、方便,不引入插件。
调研
调研了一些市面上现有的UGUI的多语言方案:
原理:给Text绑定Key,在程序开始时设置本地语言。 需附加额外脚本,无运行时动态切换语言功能。
原理及功能和上面的方案类似。
不需要附加新的脚本,基于原生的Text组件进行扩展,但无运行时动态切换语言。
基于NGUI的原理,通过附加脚本形式实现多语言,但无运行时动态切换语言。
AssetStore 上的方案:I2 Localization
功能强大,但是需要集成插件,较为臃肿,会增加使用的复杂度,并且是收费的。至于是否可以运行时动态切换语言暂时未知。
经过调研,现有的方案并不能完全满足我的需求。大多要添加额外的组件脚本,或是无动态切换语言功能,不能切换字体,使用复杂等等。
我的方案主要解决了几个痛点:
1.无需附加额外脚本进行文本的多语言。
2.支持运行时切换语言,并自动刷新多语言文本。
3.脚本上用预制体存储字体引用,多语言时替换不同字体只要替换几个预制体即可。而UGUI原生的方式是要替换项目中所有Text文件的字体属性。
4.增加菜单栏集成,创建多语言Text组件和原生Text是一致的,使用方便。
5.使用习惯和NGUI的多语言较为一致,无需插件,只需几个cs脚本即可。
具体实现
1.添加组件
2.设置字体和文本的Key(这两项不能为空)
这里的Key_String,是沿用NGUI 里的多语言方案的形式,就是采用一个Key对应多种语言文本的方式。下图中是对应的各个语言的文本及内容。
CustomFont 是也是参照NGUI的多语言方案的使用习惯,把实际的字体文件通过引用的方式存储为Prefab,这样将来替换不同语言的字体文件时,只需要替换少量的字体Prefab文件即可,而不是像UGUI官方原生的那样需要替换所有Text组件的Font。Prefab如下图:
3.一个API实现切换语言动态刷新
以下为原理:
1.总体文本方案,是将NGUI的Localization脚本拿过来,用来加载文本源数据,然后Text基础上扩展了自定义组件,用于指定Key和字体,并用管理器通过注册事件形式,来实现统一的UI切换语言后的自动刷新。
思路总的来说,是借鉴了NGUI的那套多语言方案,经过改造成为UGUI的版本,解决了UGUI 字体替换麻烦,不能指定文本Key,而且默认在切换字体后不能自动刷新的问题,这都是UGUI相比NGUI缺少的机制,这里进行了补全。中间很多东西参考了UGUI的源码,有些地方进行了重载,有些地方直接为了工具化使用,直接扒了少量代码。
2.扩展菜单实现:
public class LocalizationMenuExtension : MonoBehaviour {
[MenuItem("GameObject/UI/Text_Local", false, 2000)]
static public void AddText(MenuCommand menuCommand)
{
GameObject go = new GameObject("Text");
LocalizationText txt = go.AddComponent<LocalizationText>();
PlaceUIElementRoot(go, menuCommand);
LocalizationManager.InitValue(txt);
}
//... 有省略,上面只放最核心部分
}
3.扩展Inspectors:
[CustomEditor(typeof(LocalizationText))]
public class LocalizationTextEditor : UnityEditor.UI.TextEditor
{
public override void OnInspectorGUI()
{
LocalizationText component = (LocalizationText)target;
base.OnInspectorGUI();
component.KeyString = EditorGUILayout.TextField("Key String", component.KeyString);
component.CustomFont = (UIFontObj)EditorGUILayout.ObjectField("Custom Font", component.CustomFont, typeof(UIFontObj), true);
}
}
4.扩展Text组件:
using System;
using UnityEngine.UI;
using UnityEngine;
/// <summary>
/// Custom Text Control used for localization text.
/// </summary>
[AddComponentMenu("UI/Text_Local", 10)]
public class LocalizationText : Text
{
protected override void Awake()
{
base.Awake();
LocalizationManager.InitValue(this);
font = CustomFont.UseFont;
}
protected override void OnEnable()
{
base.OnEnable();
LocalizationManager.OnLocalize += OnLocalize;
}
protected override void OnDisable()
{
base.OnDisable();
if (LocalizationManager.OnLocalize!=null)
{
LocalizationManager.OnLocalize -= OnLocalize;
}
}
/// <summary>
/// 文本的key
/// </summary>
public string KeyString;
/// <summary>
/// 自定义字体,方便后期替换
/// </summary>
public UIFont CustomFont;
/// <summary>
/// 重新本地化,用于游戏内切换语言时调用
/// </summary>
public void OnLocalize()
{
text = Localization.Get(KeyString);
}
#region Override Part
public override string text
{
get
{
m_Text = Localization.Get(KeyString);
return m_Text;
}
set
{
if (String.IsNullOrEmpty(value))
{
if (String.IsNullOrEmpty(m_Text))
return;
m_Text = "";
SetVerticesDirty();
}
else if (m_Text != value)
{
m_Text = value;
SetVerticesDirty();
SetLayoutDirty();
}
}
}
#endregion
}
附上Demo和Package,使用的是Unity2017.4.8f1版本。
这是侑虎科技第457篇文章,感谢作者林健供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。QQ群:793972859(原群已满员)。
作者主页:https://zhuanlan.zhihu.com/p/43374662,作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!