傳回總目錄
第六章 基本架構(Framework)
- 第六章 基本架構(Framework)
- 六 配置檔案(Config Files)
- 1 設定(Setting)
- 2 管理配置檔案
- 3 讀取配置檔案(Load Config)
- 4 添加一些Config抽象
- 六 配置檔案(Config Files)
六 配置檔案(Config Files)
配置檔案的讀取,就是要讀取文本,或者反序列化。
而配置檔案的類型也是多種多樣,比如xml、txt、csv、json、protobuf等。
當然,讀取它們幾乎是相同的工作。
我們這裡建立所有配置檔案的基類
ConfigFile
。
namespace DR.Book.SRPG_Dev.Framework
{
/// <summary>
/// 所有Config的基類。
/// 參考其它繼承它的類,可以添加任何類型檔案。
/// 比如protobuf,csv,excel等檔案。
/// </summary>
public abstract class ConfigFile
{
// TODO
}
}
1 設定(Setting)
讀取方式,我們也設定成可設定的,那麼就需要一個辨別。
/// <summary>
/// 檔案讀取方式
/// </summary>
[Flags]
public enum LoadType
{
/// <summary>
/// Unity Resources檔案夾
/// </summary>
Resources = ,
/// <summary>
/// 本地WWW
/// </summary>
WWW = ,
/// <summary>
/// 需要與其它方式配合,不能單獨使用
/// </summary>
AssetBundle = ,
/// <summary>
/// 網絡WWW
/// </summary>
WWWInternet = ,
}
而無論在本地還是網絡,都需要一個路徑。而我們準備一個相對路徑。而且還要注意,比如Resources讀取是不需要擴充名的。有些檔案可以直接讀取text,但我們決定讀取
byte[]
,這是由于某些二進制檔案還是需要這樣我們自己解析。
protected struct Info
{
/// <summary>
/// 相對路徑,不要以'/'或'\'開始。
/// 如果LoadType包含AssetBundle,這裡指AssetBundle相對路徑。
/// </summary>
public string relative { get; set; }
/// <summary>
/// 名稱與擴充名,Resources與AssetBundle不需要擴充名。
/// 如果LoadType包含AssetBundle,這裡指AssetBundle名字。
/// Resources支援的文本類型,請檢視官方文檔。
/// </summary>
public string name { get; set; }
/// <summary>
/// 讀取方式
/// </summary>
public LoadType loadType { get; set; }
/// <summary>
/// 如果LoadType包含AssetBundle,AssetBundle内的路徑
/// </summary>
public string pathInAssetBundle { get; set; }
/// <summary>
/// 擷取相對路徑+檔案名稱+擴充名
/// </summary>
public string relativePath
{
get { return Path.Combine(relative, name); }
}
}
private Info m_Info;
protected ConfigFile()
{
ConstructInfo(ref m_Info);
}
/// <summary>
/// 初始化Info構造器
/// </summary>
/// <param name="info"></param>
protected abstract void ConstructInfo(ref Info info);
這樣,我們繼承它之後,可以修改info的資訊,在真正讀取它的時候,每個配置檔案都分别讀取。
當然讀取
byte[]
之後,還要進行格式化。否則不會填充我們的類。
/// <summary>
/// Format資料
/// </summary>
/// <param name="type"></param>
/// <param name="bytes"></param>
/// <param name="config"></param>
protected abstract void Format(Type type, byte[] bytes, ref ConfigFile config);
繼承它的類,必須重寫這個方法,這樣每種類型配置檔案,分别重寫不同的格式化方法。
2 管理配置檔案
這些配置檔案的存儲,這裡直接使用了一個靜态字典存儲。讀取方法放在另一個類裡。
當然你也可以删除它,自己建立一個Manager,或者為Config類單獨寫一個特殊的單例,或其他方法管理它們。
/// <summary>
/// 儲存所有Config檔案
/// </summary>
private static readonly Dictionary<Type, ConfigFile> s_ConfigDict = new Dictionary<Type, ConfigFile>();
/// <summary>
/// 擷取Config
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Get<T>() where T : ConfigFile
{
Type type = typeof(T);
ConfigFile config;
GetInternal(type, out config);
return config as T;
}
/// <summary>
/// 丢棄Config, 如果要再次使用,需要重新讀取檔案
/// </summary>
/// <typeparam name="T"></typeparam>
public static void Release<T>() where T : ConfigFile
{
s_ConfigDict.Remove(typeof(T));
}
/// <summary>
/// 丢棄所有Config,再次使用,需要重新讀取檔案
/// </summary>
public static void ReleaseAll()
{
s_ConfigDict.Clear();
}
其中
GetInternal
方法是擷取配置檔案的實作。
裡面隻是簡單的對字典的操作,如果字典中沒有就從
ConfigLoader
中讀取并格式化資料,并添加進字典。
ConfigLoader
是我們建立的專門用于讀取
byte[]
的類。
3 讀取配置檔案(Load Config)
讀取配置檔案的
byte[]
方法,放在一個單獨的類中
ConfigLoader
。
namespace DR.Book.SRPG_Dev.Framework
{
/// <summary>
/// 讀取Config的方法。
/// </summary>
public static class ConfigLoader
{
// TODO
}
}
我們将根據讀取方式去讀取檔案的
byte[]
。
根據讀取方式,讀取檔案如下:
- Resources
byte[] bytes = Resources.Load<TextAsset>(path).bytes;
// //如果是從AssetBundle讀取。
//AssetBundle bundle = Resources.Load<AssetBundle>(path);
//byte[] bytes = bundle.LoadAsset<TextAsset>(pathInAssetBundle).bytes;
//bundle.Unload(false);
- WWW
byte[] bytes;
using(WWW www = new WWW(path))
{
while (!www.isDone)
{
}
if(!string.IsNullOrEmpty(www.error))
{
Debug.LogErrorFormat(
"WWW: {0}, Path: {1}.",
www.error,
path
);
www.Dispose();
return null;
}
bytes = www.bytes;
// //如果是從AssetBundle讀取
//AssetBundle bundle = www.assetBundle;
//bytes = bundle.LoadAsset<TextAsset>(pathInAssetBundle).bytes;
//bundle.Unload(false);
}
- 在使用Resources和AssetBundle時,要注意檔案格式,并不是所有格式都支援。
- 在使用WWW時的字首,網絡要有
,而安卓包内要加http://
,其他要加jar:file://
。具體檢視Unity文檔。file://
- 在網絡讀取中,需要修改源碼,最好使用異步和逾時來控制。
- 根據平台,本地也可以用System.IO流讀取。
4 添加一些Config抽象
我們來添加一些常見的Config類型。它們的差別不大。
首先是Json:
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class JsonConfigFile : ConfigFile
{
protected override void ConstructInfo(ref Info info)
{
info.relative = "Json/";
info.name = "JsonConfig.json";
info.loadType = LoadType.WWW;
info.pathInAssetBundle = null;
}
protected sealed override void Format(Type type, byte[] bytes, ref ConfigFile config)
{
string json = Encoding.UTF8.GetString(bytes).Trim();
FormatBuffer(json);
}
/// <summary>
/// Bytes轉換成json後執行
/// </summary>
/// <param name="buffer"></param>
protected virtual void FormatBuffer(string buffer)
{
JsonUtility.FromJsonOverwrite(buffer, this);
}
}
}
其次是Xml:
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class XmlConfigFile : ConfigFile
{
protected override void ConstructInfo(ref Info info)
{
info.relative = "Xml/";
info.name = "XmlConfig.xml";
info.loadType = LoadType.WWW;
info.pathInAssetBundle = null;
}
protected sealed override void Format(Type type, byte[] bytes, ref ConfigFile config)
{
XmlConfigFile buffer;
using (MemoryStream ms = new MemoryStream(bytes))
{
XmlSerializer xs = new XmlSerializer(type);
buffer = xs.Deserialize(ms) as XmlConfigFile;
}
if (buffer != null)
{
config = FormatBuffer(buffer);
}
}
/// <summary>
/// 反序列化完成後執行
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
protected abstract XmlConfigFile FormatBuffer(XmlConfigFile buffer);
}
}
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class XmlDocConfigFile : ConfigFile
{
protected override void ConstructInfo(ref Info info)
{
info.relative = "Xml/";
info.name = "XmlDocConfig.xml";
info.loadType = LoadType.WWW;
info.pathInAssetBundle = null;
}
protected sealed override void Format(Type type, byte[] bytes, ref ConfigFile config)
{
string xml = Encoding.UTF8.GetString(bytes).Trim();
XmlDocument buffer = new XmlDocument();
buffer.LoadXml(xml);
FormatBuffer(buffer);
}
/// <summary>
/// Bytes轉換成XmlDocument後執行
/// </summary>
/// <param name="buffer"></param>
protected abstract void FormatBuffer(XmlDocument buffer);
}
}
最後是Txt:
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class TxtConfigFile : ConfigFile
{
protected override void ConstructInfo(ref Info info)
{
info.relative = "Txt/";
info.name = "TxtConfig.txt";
info.loadType = LoadType.WWW;
info.pathInAssetBundle = null;
}
protected sealed override void Format(Type type, byte[] bytes, ref ConfigFile config)
{
string text = Encoding.UTF8.GetString(bytes).Trim();
FormatBuffer(text);
}
/// <summary>
/// Bytes轉換成text後執行
/// </summary>
/// <param name="buffer"></param>
protected abstract void FormatBuffer(string buffer);
}
}
你可以參考這些自己寫其他類型,比如protobuf,csv等。