使用c#反射實現UGUI文字顯示的國際化
轉載請標明出處:http://blog.csdn.net/u013015161/article/details/46319143
這兩天要實現遊戲介面的國際化, 先在網上找了一下,沒有找到現成的方案(NGUI的倒是有), 就自己實現了一下。
先看一下效果:
使用者只需要給需要國際化的Text物件拖入TextLocalization元件,設定元件中Text Name的值,即可自動獲得該值對應的中英文物件,實現上述國際化效果。
實現步驟:
1、新建Localization抽象類及其兩個子類:Localization_CN和Localization_EN, 分別儲存中英文字串。 程式碼如下:
可以看到,兩個子類實現了父類的屬性。父類中分別由兩個子類的物件,但都由父類來指向,方便統一呼叫屬性,即Instance訪問。取字串時, 只要呼叫父類static屬性Instance,訪問其屬性,即可根據當前語言型別自動返回中文或者英文字串。using UnityEngine; using System.Collections; public abstract class Localization { public static string language = PlayerPrefs.GetString("language"); string play; public abstract string Play { get; } string settings; public abstract string Settings { get; } string back; public abstract string Back { get; } string welcome; public abstract string Welcome { get; } private static Localization instance_CN = new Localization_CN(); private static Localization instance_EN = new Localization_EN(); public static Localization Instance { get { switch(language) { case "Chinese": return instance_CN; case "English": return instance_EN; default: return instance_EN; } } } } public class Localization_CN :Localization { string play = "開始遊戲"; public override string Play { get { return play; } } string settings = "設定"; public override string Settings { get { return settings; } } string back = "返回"; public override string Back { get { return back; } } string welcome = "歡迎來到第二個頁面"; public override string Welcome { get { return welcome; } } } public class Localization_EN :Localization { string play = "PLAY"; public override string Play { get { return play; } } string settings = "SETTINGS"; public override string Settings { get { return settings; } } string back = "BACK"; public override string Back { get { return back; } } string welcome = "welcome to the second page"; public override string Welcome { get { return welcome; } } }
2、新建文字的國際化指令碼:TextLocalization.cs。 程式碼如下:
這個指令碼關鍵在TextLocalizationChange()函式。通過設定好的textName,利用c#的反射原理, 找到當前對應的Localization物件的屬性值,從而實現國際化。在使用者手動更改遊戲語言設定時,該方法通過BroadcastMessage被呼叫, 同時在Start階段主動呼叫一次。using UnityEngine; using UnityEngine.UI; using System.Collections; using System; using System.Reflection; public class TextLocalization : MonoBehaviour { /*文字對應的屬性名,首字母大寫*/ public string textName; void TextLocalizationChange() { /*使用反射, 通過textName獲取屬性值*/ Type t = Localization.Instance.GetType(); PropertyInfo property = t.GetProperty (textName); if (null != property ) { Debug.Log(property.GetValue (Localization.Instance, null).ToString ()); this.GetComponent<Text> ().text = property.GetValue (Localization.Instance, null).ToString (); } } void Start() { TextLocalizationChange (); } }
使用時, 將該指令碼拖動到需要國際化的Text物件上,新增上合適的TextName值即可。 如圖:
在初始化和修改語言種類時, 會自動使用相應Localization物件的同名屬性進行文字設定。
3、建立空物體,將其作為所有canvas的父物體。這樣做是由於BroadcastMessage(string Name)方法只能invoke本物體及其子物體的相關方法,所以需要這樣一個父物體,才能呼叫所有Text物件上的TextLocalizationChange。
4、建立空物體,所謂Game Controller, 編寫GameController指令碼拖給它。GameController.cs如下:
using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour {
public GameObject canvas1;
public GameObject canvas2;
public GameObject canvas_home;
public void OnPlayClick()
{
//顯示canvas2
canvas1.GetComponent<Canvas> ().enabled = false;
canvas2.GetComponent<Canvas> ().enabled = true;
}
public void OnBackClick()
{
//顯示canvas1
canvas1.GetComponent<Canvas> ().enabled = true;
canvas2.GetComponent<Canvas> ().enabled = false;
}
public void OnChineseClick()
{
Localization.language = "Chinese";
//本地儲存中language欄位為中文
PlayerPrefs.SetString("language", "Chinese");
//傳送廣播 ,更改文字
canvas_home.BroadcastMessage ("TextLocalizationChange");
}
public void OnEnglishClick()
{
Localization.language = "English";
PlayerPrefs.SetString("language", "English");
canvas_home.BroadcastMessage ("TextLocalizationChange");
}
}
裡面實現了中文按鈕和英文按鈕, play按鈕和back按鈕的點選事件,可在編輯器中分別關聯上相應按鈕。canvas1、canvas2和canvas_home通過編輯器拖動賦值,分別指向兩個canvas以及步驟3中的父物體。可以看到點選中英文按鈕,會呼叫canvas_home的BroadcastMessage, 更改所有含有TextLocalization元件的Text物件的text值。
這樣,就簡單的通過反射實現了UGUI文字顯示的國際化。這個主要是一個實驗性質的實現,其實如果使用Dictionaray<String, String>來儲存國際化資料,而不是屬性,就可以直接通過Text Name作為鍵訪問資料了,而不需要使用反射去呼叫屬性,不過效率不一定高,為了保證只讀性,可能還需要重寫Dictionary所有可以修改資料內容的方法。
這次的實現已經傳到共享的git上了,場景為ugui_localization.unity, 可供參考。
專案地址: