1. 程式人生 > >使用c#反射實現UGUI文字顯示的國際化

使用c#反射實現UGUI文字顯示的國際化

轉載請標明出處:http://blog.csdn.net/u013015161/article/details/46319143

這兩天要實現遊戲介面的國際化, 先在網上找了一下,沒有找到現成的方案(NGUI的倒是有), 就自己實現了一下。

先看一下效果:


使用者只需要給需要國際化的Text物件拖入TextLocalization元件,設定元件中Text Name的值,即可自動獲得該值對應的中英文物件,實現上述國際化效果。

實現步驟:

1、新建Localization抽象類及其兩個子類:Localization_CN和Localization_EN, 分別儲存中英文字串。 程式碼如下:

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;
		}
	}
}
可以看到,兩個子類實現了父類的屬性。父類中分別由兩個子類的物件,但都由父類來指向,方便統一呼叫屬性,即Instance訪問。取字串時, 只要呼叫父類static屬性Instance,訪問其屬性,即可根據當前語言型別自動返回中文或者英文字串。

2、新建文字的國際化指令碼:TextLocalization.cs。 程式碼如下:

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 ();
	}
}
這個指令碼關鍵在TextLocalizationChange()函式。通過設定好的textName,利用c#的反射原理, 找到當前對應的Localization物件的屬性值,從而實現國際化。在使用者手動更改遊戲語言設定時,該方法通過BroadcastMessage被呼叫, 同時在Start階段主動呼叫一次。

使用時, 將該指令碼拖動到需要國際化的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, 可供參考。

專案地址: