第一次写博客,直接进入正题!~~
实现功能的本质,其实就是切换图片。
那么我们首先要做一些准备工作,也是我觉得最枯燥繁琐的第一步:多语言文档。
这里我选择采用的是Json文档,下面是我写的Json格式。
{
"SCENE":[
{"PATH":"Login*Canvas/Image","TYPE":[{"CN":"1","TW":"1","EN":"1" }]},
{"PATH":"Login*Canvas/Image1","TYPE":[{"CN":"2","TW":"2","EN":"2" }]},
{"PATH":"Login*Canvas/Image2","TYPE":[{"CN":"3","TW":"3","EN":"3" }]},
{"PATH":"Lobby*Canvas/Image","TYPE":[{"CN":"1","TW":"1","EN":"1" }]},
{"PATH":"Lobby*Canvas/Image1","TYPE":[{"CN":"2","TW":"2","EN":"2" }]},
{"PATH":"Lobby*Canvas/Image2","TYPE":[{"CN":"3","TW":"3","EN":"3" }]}
]
}
我是直接写成txt格式,放到Resources文件夹里面。
可以看出来,SCENE是一个集合,里面包含两个键“PATH”和“TYPE”,
“PATH”的值是“场景*路径”,“TYPE”的值又是一个集合,里面包含需要的语言类型和对应的图片编号。 这样写比较方便,因为会用到这样的格式。
public class LanguageTpye
{
public List<LanguageInfo> SCENE;
}
public class LanguageInfo
{
public string PATH;
public List<ImgTpye> TYPE;
}
public class ImgTpye
{
public string CN;
public string TW;
public string EN;
}
这里定义的类,就对应了上面的Json格式。切记变量名字一定要和Json里的键名一样。
前戏就到这里,下面进入正题。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using LitJson;
public class LanguageCtrl : MonoBehaviour
{
public static LanguageCtrl instance = null;
//每一个场景对应一个字典
public Dictionary<string, List<ImgTpye>> loginPathDic;
public Dictionary<string, List<ImgTpye>> lobbyPathDic;
public int index; //语言类型的序号
public bool DontDestroy = true;
void Awake()
{
if (instance != null)
{
GameObject.Destroy(this.gameObject);
return;
}
instance = this;
if (DontDestroy)
DontDestroyOnLoad(this);
index = 0;
loginPathDic = new Dictionary<string, List<ImgTpye>>();
lobbyPathDic = new Dictionary<string, List<ImgTpye>>();
ReloadLanguageData("language_test");
DisplayLanguageList(languageTpye);
}
LanguageTpye languageTpye;
/// <summary>
/// 将文档转化成Json文件
/// </summary>
private void ReloadLanguageData(string path)
{
TextAsset s = Resources.Load<TextAsset>(path);
string tmp = s.text;
languageTpye = JsonMapper.ToObject<LanguageTpye>(tmp);
JsonMapper.ToJson(languageTpye);
}
/// <summary>
/// 解析Json文件
/// </summary>
/// <param name="languageTpye"></param>
private void DisplayLanguageList(LanguageTpye languageTpye)
{
if (languageTpye == null) return;
for (int i = 0; i < languageTpye.SCENE.Count; i++)
{
string[] path = languageTpye.SCENE[i].PATH.Split('*');
//对PAth的值进行切割'*',第一个值为场景,第二个值为路径
//根据场景,对每个字典进行赋值
switch (path[0])
{
case "Login":
loginPathDic.Add(path[1], languageTpye.SCENE[i].TYPE);
break;
case "Lobby":
lobbyPathDic.Add(path[1], languageTpye.SCENE[i].TYPE);
break;
default:
break;
}
}
}
/// <summary>
/// 切换图片
/// </summary>
/// <param name="index"></param>
/// <param name="scenePathDic"></param>
public void ChangeLanguage(int index, Dictionary<string, List<ImgTpye>> scenePathDic)
{
string langType = "";
string imgTpye = "";
foreach (string str in scenePathDic.Keys)
{
//Debug.Log(str);
Image image = GameObject.Find(str).GetComponent<Image>();
if (index == 0)
{
langType = "CN/";
imgTpye = scenePathDic[str][0].CN;
}
else if (index == 1)
{
langType = "TW/";
imgTpye = scenePathDic[str][0].TW;
}
else if (index == 2)
{
langType = "EN/";
imgTpye = scenePathDic[str][0].EN;
}
image.sprite = Resources.Load<Sprite>("Languages/" + langType + imgTpye);
}
}
}
LitJson的插件就请自行在网上下载了。
最后切换语言的button,实际上就是切换这里的index,然后调用ChangeLanguage就可以了。这里我用的Toggle,大同小异。
public void ChangeCN()
{
if (cn_tg.isOn)
{
LanguageCtrl.instance.index = 0;
LanguageCtrl.instance.ChangeLanguage(LanguageCtrl.instance.index, LanguageCtrl.instance.loginPathDic);
Debug.Log("切换中文");
}
}
public void ChangeEN()
{
if (en_tg.isOn)
{
LanguageCtrl.instance.index = 2;
LanguageCtrl.instance.ChangeLanguage(LanguageCtrl.instance.index, LanguageCtrl.instance.loginPathDic);
Debug.Log("切换English");
}
}
到这里单个场景的多语言切换已经完成了,但是涉及到切换场景的时候,要怎么保证一致呢?
在每个场景的Awake里面加一句话就可以了
void Awake()
{
LanguageCtrl.instance.ChangeLanguage(LanguageCtrl.instance.index, LanguageCtrl.instance.lobbyPathDic);
}
因为目前项目里只涉及了图片版的多语言,但是我想文字版的应该也是差不多的,只是把Json里的图片编号变成文字内容就行了。
最后友情提醒一句,如果使用图片做多语言,一定要让美术把不同语言的图做成同样的分辨率,可以省去很多麻烦。