写项目时遇到多语言的问题,之前也跟导师聊过项目内的多语言,稍微总结下
多语言的思路
介绍下多语言的两种做法思路,一种是组件运行时处理,一种是运行前生成多个预制体与多份代码进行保存
组件处理
需要一个key值对应各语言的文本表。
对于静态文本,将key存储到组件中,运行时读取文本表将key转为对应语言的文本。动态文本运行时直接将key转为对应语言的文本。
预制体
可以简单克隆多个预制体,根据路径区分对应语言的预制体,代码也是类似区分。
优缺点
预制体相比于组件处理:
优点:
- 运行效率更高,内存占用更小
缺点:
-
包体更大
-
需要重启重新加载预设与代码,无法运行时切换
一般来说还是选择组件处理多,接下来讲的实现方法也是类似的。
具体实现
Localization包
可以直接使用Untiy官方的Localization包,对于要处理的组件点击右上角Localize,会自动添加组件,放入key值就可以了,静态文本可以不编写代码完成。
LocalizedText
因为感觉Localization配表各方面比较麻烦(打算和其他地方也在用的配表方法统一),所以就还是自己写了,也不是很难,主要是拓展了TextMeshPro,添加一个key值,实时转换的话自己写一个事件吧,其实Localization也是这么做的。
具体代码
using TMPro;
using TMPro.EditorUtilities;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
public class LocalizedText : TextMeshProUGUI
{
public string key = "";
private bool hasChanged = false;
public override string text
{
get => base.text;
set
{
setText(value);
}
}
private void setText(string text)
{
base.text = text;
if (!EditorApplication.isPlaying) return;
hasChanged = true;
}
protected override void Awake()
{
base.Awake();
if (!EditorApplication.isPlaying) return;
if (!hasChanged)
{
text = LocalizationManager.Instance.GetLanguage(key);
hasChanged = true;
}
}
}
[CustomEditor(typeof(LocalizedText), true), CanEditMultipleObjects]
public class LocalizedTextEditor : TMP_EditorPanelUI
{
private SerializedProperty key;
protected override void OnEnable()
{
base.OnEnable();
key = serializedObject.FindProperty("key");
}
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(key, new GUIContent("Key"));
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
base.OnInspectorGUI();
}
}
LocalizedText实现
setText方法记录了组件运行时被代码更改的情况,这种情况下就不会进行首次的静态文本的转换,EditorApplication.isPlaying
代表目前编辑器正在运行,只有运行时才会更改。
实时转换的话加个事件来重设文本即可。
Editor类
主要是在Inspector下添加窗口,注意serializedObject.ApplyModifiedProperties();
会将在窗口更改的属性应用到你设置的property中。