很多游戏中都有语言设置选项,NGUI插件中自带了国际化脚本,但是灵活性较低,而且目前项目是UGUI,以下是修改后,以便记录。
Localization和NGUI中用法一样,挂在在一个不销毁的游戏物体上,并设置当前语言,及所有语言的陪标
//----------------------------------------------
//----------------------------------------------
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class Localization : MonoBehaviour
{
static Localization mInst;
static public Localization instance
{
get
{
if (mInst == null)
{
mInst = Object.FindObjectOfType(typeof(Localization)) as Localization;
if (mInst == null)
{
GameObject go = new GameObject("_Localization");
DontDestroyOnLoad(go);
mInst = go.AddComponent();
}
}
return mInst;
}
}
public string startingLanguage;
public TextAsset[] languages;
Dictionary mDictionary = new Dictionary();
string mLanguage;
public string currentLanguage
{
get
{
//if (string.IsNullOrEmpty(mLanguage))
{
currentLanguage = PlayerPrefs.GetString("Language");
if (string.IsNullOrEmpty(mLanguage))
{
currentLanguage = startingLanguage;
if (string.IsNullOrEmpty(mLanguage) && (languages != null && languages.Length > 0))
{
currentLanguage = languages[0].name;
}
}
}
return mLanguage;
}
set
{
if (mLanguage != value)
{
startingLanguage = value;
if (!string.IsNullOrEmpty(value))
{
if (languages != null)
{
for (int i = 0, imax = languages.Length; i < imax; ++i)
{
TextAsset asset = languages[i];
if (asset != null && asset.name == value)
{
Load(asset);
return;
}
}
}
TextAsset txt = Resources.Load(value, typeof(TextAsset)) as TextAsset;
if (txt != null)
{
Load(txt);
return;
}
}
mDictionary.Clear();
PlayerPrefs.DeleteKey("Language");
}
}
}
///
/// Determine the starting language.
///
void Awake() { if (mInst == null) { mInst = this; DontDestroyOnLoad(gameObject); } else Destroy(gameObject); }
///
/// Start with the specified starting language.
///
void Start() { if (!string.IsNullOrEmpty(startingLanguage)) currentLanguage = startingLanguage; }
///
/// Oddly enough... sometimes if there is no OnEnable function in Localization, it can get the Awake call after UILocalize's OnEnable.
///
void OnEnable() { if (mInst == null) mInst = this; }
///
/// Remove the instance reference.
///
void OnDestroy() { if (mInst == this) mInst = null; }
///
/// Load the specified asset and activate the localization.
///
void Load(TextAsset asset)
{
mLanguage = asset.name;
PlayerPrefs.SetString("Language", mLanguage);
ByteReader reader = new ByteReader(asset);
mDictionary = reader.ReadDictionary();
// Broadcast("OnLocalize");
}
public string Get(int key)
{
string val;
return (mDictionary.TryGetValue(key, out val)) ? val : null;
}
}
//----------------------------------------------
// NGUI: Next-Gen UI kit
// Copyright © 2011-2012 Tasharen Entertainment
//----------------------------------------------
using UnityEngine;
using System.Text;
using System.Collections.Generic;
///
/// MemoryStream.ReadLine has an interesting oddity: it doesn't always advance the stream's position by the correct amount:
/// http://social.msdn.microsoft.com/Forums/en-AU/Vsexpressvcs/thread/b8f7837b-e396-494e-88e1-30547fcf385f
/// Solution? Custom line reader with the added benefit of not having to use streams at all.
///
public class ByteReader
{
byte[] mBuffer;
int mOffset = 0;
public ByteReader(byte[] bytes) { mBuffer = bytes; }
public ByteReader(TextAsset asset) { mBuffer = asset.bytes; }
///
/// Whether the buffer is readable.
///
public bool canRead { get { return (mBuffer != null && mOffset < mBuffer.Length); } }
///
/// Read a single line from the buffer.
///
static string ReadLine(byte[] buffer, int start, int count)
{
#if UNITY_FLASH
// Encoding.UTF8 is not supported in Flash :(
StringBuilder sb = new StringBuilder();
int max = start + count;
for (int i = start; i < max; ++i)
{
byte byte0 = buffer[i];
if ((byte0 & 128) == 0)
{
// If an UCS fits 7 bits, its coded as 0xxxxxxx. This makes ASCII character represented by themselves
sb.Append((char)byte0);
}
else if ((byte0 & 224) == 192)
{
// If an UCS fits 11 bits, it is coded as 110xxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
int ch = (byte0 & 31) << 6;
ch |= (byte1 & 63);
sb.Append((char)ch);
}
else if ((byte0 & 240) == 224)
{
// If an UCS fits 16 bits, it is coded as 1110xxxx 10xxxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
if (++i == count) break;
byte byte2 = buffer[i];
if (byte0 == 0xEF && byte1 == 0xBB && byte2 == 0xBF)
{
// Byte Order Mark -- generally the first 3 bytes in a Windows-saved UTF-8 file. Skip it.
}
else
{
int ch = (byte0 & 15) << 12;
ch |= (byte1 & 63) << 6;
ch |= (byte2 & 63);
sb.Append((char)ch);
}
}
else if ((byte0 & 248) == 240)
{
// If an UCS fits 21 bits, it is coded as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
if (++i == count) break;
byte byte2 = buffer[i];
if (++i == count) break;
byte byte3 = buffer[i];
int ch = (byte0 & 7) << 18;
ch |= (byte1 & 63) << 12;
ch |= (byte2 & 63) << 6;
ch |= (byte3 & 63);
sb.Append((char)ch);
}
}
return sb.ToString();
#else
return Encoding.UTF8.GetString(buffer, start, count);
#endif
}
///
/// Read a single line from the buffer.
///
public string ReadLine()
{
int max = mBuffer.Length;
// Skip empty characters
while (mOffset < max && mBuffer[mOffset] < 32) ++mOffset;
int end = mOffset;
if (end < max)
{
for (;;)
{
if (end < max)
{
int ch = mBuffer[end++];
if (ch != '\n' && ch != '\r') continue;
}
else ++end;
string line = ReadLine(mBuffer, mOffset, end - mOffset - 1);
mOffset = end;
return line;
}
}
mOffset = max;
return null;
}
///
/// Assume that the entire file is a collection of key/value pairs.
///
public Dictionary ReadDictionary()
{
Dictionary dict = new Dictionary();
char[] separator = new char[] { '=' };
while (canRead)
{
string line = ReadLine();
if (line == null) break;
#if UNITY_FLASH
string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries);
#else
string[] split = line.Split(separator, 2, System.StringSplitOptions.RemoveEmptyEntries);
#endif
if (split.Length == 2)
{
int key = int.Parse(split[0].Trim());
string val = split[1].Trim();
dict[key] = val;
}
}
return dict;
}
}
//----------------------------------------------
//----------------------------------------------
using UnityEngine;
using UnityEngine.UI;
public class UILocalize : MonoBehaviour
{
///
/// Localization key.
///
public string Atlas;
public string key;
string mLanguage;
bool mStarted = false;
///
/// This function is called by the Localization manager via a broadcast SendMessage.
///
void OnLocalize(Localization loc) { if (mLanguage != loc.currentLanguage) Localize(); }
///
/// Localize the widget on enable, but only if it has been started already.
///
void OnEnable() { if (mStarted && Localization.instance != null) Localize(); }
///
/// Localize the widget on start.
///
void Start()
{
mStarted = true;
if (Localization.instance != null) Localize();
}
///
/// Force-localize the widget.
///
public void Localize(string key = null)
{
if (key == null)
key = this.key;
Localization loc = Localization.instance;
MaskableGraphic w = GetComponent();
Text lbl = w as Text;
Image sp = w as Image;
// If no localization key has been specified, use the label's text as the key
if (string.IsNullOrEmpty(mLanguage) && string.IsNullOrEmpty(key) && lbl != null)
key = lbl.text;
// If we still don't have a key, use the widget's name
string val = string.IsNullOrEmpty(key) ? w.name : loc.Get(int.Parse(key));
if (val != null)
{
if (lbl != null)
{
lbl.text = val;
}
else if (sp != null)
{
if (Atlas == null)
return;
sp.sprite = DoRo.Manager.LoadManager.Instance.LoadSprite(Atlas, val);
}
}
mLanguage = loc.currentLanguage;
}
}