1. 程式人生 > 實用技巧 >遊戲UI框架設計(五): 配置管理與應用

遊戲UI框架設計(五): 配置管理與應用

遊戲UI框架設計(五)

--配置管理與應用



在開發企業級遊戲/VR/AR產品時候,我們總是希望可以總結出一些通用的技術體系,框架結構等,為簡化我們的開發起到“四兩撥千金”的作用。所謂“配置管理”是指一個遊戲專案(軟體專案),很多需要經常變化的需求或者資料,最好以配置檔案的形式存在,從而代替“硬編碼”方式。


這裡筆者就對遊戲產品中大量應用到動態載入的情形,開發出一套通用的配置管理(指令碼)工具。該工具可以很方便的對於具備“鍵值對”特性的配置檔案做統一的資料提取處理,特別適合如下應用情形等:


1:“UI預設”/“遊戲物件預設”的動態載入。

2:企業級Log 日誌系統中關於配置資訊(日誌的儲存路徑、日誌級別資訊)的動態載入。

3:資源(語言)國際化系統中關於語言資訊的動態載入。


下圖給出本UI框架用到的"語言國際化"對應的Json 配置檔案:


wKioL1k0rJChHLUqAACGc_VGzhc281.jpg-wh_50


(“語言國際化”中文資訊的Json配置檔案)



目前(2017)國際國內普遍採用的配置管理方式主要有兩種: XML與Json 方式。

兩者各有優缺點:

XML: 對於資料的精確表示、易讀性很高。

微軟很多的專案都內建對XML作為配置檔案的支援。

(例如: 網站專案:ASP.Net、 WinForm 等)

缺點是讀寫速度慢,這個問題在移動端尤其突出。


Json: 讀寫速度快,但是易讀性沒有XML好,但是可以接受。

所以本框架專案都採用Json作為配置檔案。



考慮到目前移動端遊戲/VR/AR產品的大量應用,所以筆者在此重點介紹基於Json配置檔案的資料解析與配置管理。(Json比傳統的XML作為配置檔案使用,具備解析速度快,檔案尺寸小等突出優點)


什麼是Json

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。 JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網路傳輸速率)。



JSON 語法 (JSON 語法是 JavaScript 物件表示語法的子集)

特點:

資料在鍵值對中,資料由逗號分隔。

花括號儲存物件,方括號儲存陣列。

JSON 資料的書寫格式是:名稱/值對 "firstName":"John"

具體示例:


wKiom1k0rKfCX6hJAAA4oTWKn3g387.jpg-wh_50



Json的解析方式:


目前(2017)國際國內對於Json 的解析主要有以下幾種方式

  • .NET自帶的執行時序列化和反序列化json工具。

名稱空間 System.Runtime.Serialization.Json

缺點是需要編寫大量程式碼,自己來封裝一些實用方法,不推薦。

  • 外掛解析:

目前國內用的最多的Json解析外掛: litejson

由於Unity公司也看到了Unity專案中對於大量Json 檔案解析操作的需求,所以在Unity5.3以上版本開始原生提供Json的解析API,如下圖:


wKiom1k0rMCj9sROAADy7TYtNQU261.png-wh_50



對於Json 的初學者,為了更好的理解後面的配置管理技術講解,特提供使用Unity的API 對Json 配置檔案的解析示例:


Json基本解析示例

  • 示例1:


對於Unity 原生支援Json 解析方法的最簡測試演示。

namespaceTest
{
[Serializable]
publicclassHero
{
//名稱
publicstringName;
//等級
publicLevelMyLevel;

}
}

namespaceTest
{
[Serializable]
publicclassLevel
{
publicintHeroLevel;

}
}


/***
*
*Title:"SUIFW"UI框架專案
*主題:演示Unity對Json解析API

usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;

namespaceTest
{
publicclassTestUnityJson:MonoBehaviour{


voidStart(){
HeroheroObj=newHero();
heroObj.Name="郭靖";
heroObj.MyLevel=newLevel(){HeroLevel=800};
//相當於如下寫法
//Levellev=newLevel();
//lev.HeroLevel=800;
//heroObj.MyLevel=lev;

//方法1:Json序列化工作(物件-->檔案)
stringstrHeroInfo=JsonUtility.ToJson(heroObj);
Debug.Log("測試1:得到的序列化後的字串="+strHeroInfo);

//方法2:反序列化(Json檔案-->物件)
HeroheroInfo2=JsonUtility.FromJson<Hero>(strHeroInfo);
Debug.Log("測試2:得到反序列化物件數值,名稱:"+heroInfo2.Name+"等級:"+heroInfo2.MyLevel.HeroLevel);

//方法3:測試覆蓋反序列化。
Herohero=newHero();
hero.Name="楊過";
hero.MyLevel=newLevel(){HeroLevel=500};

//Json序列化
stringheroInfo3=JsonUtility.ToJson(hero);
//測試覆蓋反序列化
JsonUtility.FromJsonOverwrite(heroInfo3,heroObj);
Debug.Log("測試3,得到再次反序列化覆蓋的物件資訊,名稱:"+heroObj.Name+"等級:"+heroObj.MyLevel.HeroLevel);


}
}
}



  • 示例2:

對於Json 檔案的實戰性測試用例演示。

/***
*
*Title:"SUIFW"UI框架專案
*主題:對於Unity中Resource目錄下的Json檔案的解析Demo
*Description:
*功能:yyy
*
*Date:2017
*Version:0.1版本
*ModifyRecoder:
*
*
*/
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;

namespaceTest
{
publicclassTestUnityJson2:MonoBehaviour{


voidStart()
{
//提取檔案,得到字串資料
TextAssetTaObj=Resources.Load<TextAsset>("People");
//反序列化檔案-->物件
PersonInfoperInfo=JsonUtility.FromJson<PersonInfo>(TaObj.text);
//顯示物件中資料
foreach(PeopleperinperInfo.People)
{
Debug.Log("");
Debug.Log(string.Format("name={0},Age={1}",per.Name,per.Age));
}
}
}
}



以上程式碼解釋如下:


Unity(5.3以上版本)提供的JsonUtility 提供了三個重要方法


JsonUtility.ToJson() //表示進行序列化操作,把物件序列化為字串。

JsonUtility.FromJson() ;//表示進行反序列化操作,把Json字串反序列化為物件。

JsonUtility.FromJsonOverwrite();//是覆蓋方式進行反序列化。



有了以上技術儲備,我們就可以進行開發“通用配置管理器”了。


第1步: 首先定義通用配置管理器介面與輔助類。


程式碼如下:

/***
*
*Title:"SUIFW"UI框架專案
*主題:通用配置管理器介面
*Description:
*功能:
*基於“鍵值對”配置檔案的通用解析
*
*Date:2017
*Version:0.1版本
*ModifyRecoder:
*
*
*/

usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;

namespaceSUIFW
{
publicinterfaceIConfigManager{

///<summary>
///只讀屬性:應用設定
///功能:得到鍵值對集合資料
///</summary>
Dictionary<string,string>AppSetting{get;}

///<summary>
///得到配置檔案(AppSeting)最大的數量
///</summary>
///<returns></returns>
intGetAppSettingMaxNumber();

}

[Serializable]
internalclassKeyValuesInfo
{
//配置資訊
publicList<KeyValuesNode>ConfigInfo=null;
}

[Serializable]
internalclassKeyValuesNode
{
//鍵
publicstringKey=null;
//值
publicstringValue=null;
}
}



第2步: 定義Json 解析異常類。


Json 的解析過程如果出錯,推薦使用我們自己定義的異常處理,為了更好的發現程式錯誤,所以自定義Json 解析異常類定義如下:


/***
*
*Title:"SUIFW"UI框架專案
*主題:Json解析異常
*Description:
*功能:專門負責對於JSon由於路徑錯誤,或者Json格式錯誤造成的異常,進行捕獲。
*
*Date:2017
*Version:0.1版本
*ModifyRecoder:
*
*
*/

usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;

namespaceSUIFW
{
publicclassJsonAnlysisException:Exception{
publicJsonAnlysisException():base(){}
publicJsonAnlysisException(stringexceptionMessage):base(exceptionMessage){}
}
}


第3步:定義“配置管理器”類


開發實現IConfigManager 介面的通用配置管理器


/***
*
*Title:"SUIFW"UI框架專案
*主題:基於Json配置檔案的“配置管理器”
*Description:
*功能:
*
*Date:2017
*Version:0.1版本
*ModifyRecoder:
*
*
*/

usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;

namespaceSUIFW
{
publicclassConfigManagerByJson:IConfigManager
{
//儲存(鍵值對)應用設定集合
privatestaticDictionary<string,string>_AppSetting;

///<summary>
///只讀屬性:得到應用設定(鍵值對集合)
///</summary>
publicDictionary<string,string>AppSetting
{
get{return_AppSetting;}
}

///<summary>
///建構函式
///</summary>
///<paramname="jsonPath">Json配置檔案路徑</param>
publicConfigManagerByJson(stringjsonPath)
{
_AppSetting=newDictionary<string,string>();
//初始化解析Json資料,載入到(_AppSetting)集合。
InitAndAnalysisJson(jsonPath);
}

///<summary>
///得到AppSetting的最大數值
///</summary>
///<returns></returns>
publicintGetAppSettingMaxNumber()
{
if(_AppSetting!=null&&_AppSetting.Count>=1)
{
return_AppSetting.Count;
}
else
{
return0;
}
}

///<summary>
///初始化解析Json資料,載入到集合眾。
///</summary>
///<paramname="jsonPath"></param>
privatevoidInitAndAnalysisJson(stringjsonPath)
{
TextAssetconfigInfo=null;
KeyValuesInfokeyvalueInfoObj=null;

//引數檢查
if(string.IsNullOrEmpty(jsonPath))return;
//解析Json配置檔案
try{
configInfo=Resources.Load<TextAsset>(jsonPath);
keyvalueInfoObj=JsonUtility.FromJson<KeyValuesInfo>(configInfo.text);
}
catch{
thrownewJsonAnlysisException(GetType()+"/InitAndAnalysisJson()/JsonAnalysisException!ParameterjsonPath="+jsonPath);
}
//資料載入到AppSetting集合中
foreach(KeyValuesNodenodeInfoinkeyvalueInfoObj.ConfigInfo)
{
_AppSetting.Add(nodeInfo.Key,nodeInfo.Value);
}
}



}
}


程式碼說明:

以上定義的“配置管理器”,可以對所有具備“鍵值對”特性的Json 配置檔案,做統一資料提取工作,從而對於“UI預設”、“遊戲物件”、“日誌配置檔案”、“語言國際化”等資訊,可以做統一處理,極大提供開發效率。以下筆者提供本UI框架需要用到的除企業日誌系統外,其他兩種配置檔案的截圖,供參考。


wKioL1k0rjij79arAAAquZzQSKg402.png-wh_50


(企業級Log日誌中使用到的配置資訊)


wKioL1k0rkbCRqAfAAF8ct-hdf8338.png-wh_50


(“UI預設” 路徑資訊Json配置檔案)

本篇就先寫到這,下篇 "遊戲UI框架設計(6)_訊息傳遞中心" 繼續。



轉載於:https://blog.51cto.com/liuguozhu/1932167