遊戲UI框架設計(五): 配置管理與應用
遊戲UI框架設計(五)
--配置管理與應用
在開發企業級遊戲/VR/AR產品時候,我們總是希望可以總結出一些通用的技術體系,框架結構等,為簡化我們的開發起到“四兩撥千金”的作用。所謂“配置管理”是指一個遊戲項目(軟件項目),很多需要經常變化的需求或者數據,最好以配置文件的形式存在,從而代替“硬編碼”方式。
這裏筆者就對遊戲產品中大量應用到動態加載的情形,開發出一套通用的配置管理(腳本)工具。該工具可以很方便的對於具備“鍵值對”特性的配置文件做統一的數據提取處理,特別適合如下應用情形等:
1:“UI預設”/“遊戲對象預設”的動態加載。
2:企業級Log 日誌系統中關於配置信息(日誌的保存路徑、日誌級別信息)的動態加載。
3:資源(語言)國際化系統中關於語言信息的動態加載。
下圖給出本UI框架用到的"語言國際化"對應的Json 配置文件:
(“語言國際化”中文信息的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"
具體示例:
Json的解析方式:
目前(2017)國際國內對於Json 的解析主要有以下幾種方式
- .NET自帶的運行時序列化和反序列化json工具。
命名空間 System.Runtime.Serialization.Json
缺點是需要編寫大量代碼,自己來封裝一些實用方法,不推薦。
- 插件解析:
目前國內用的最多的Json解析插件: litejson
由於Unity公司也看到了Unity項目中對於大量Json 文件解析操作的需求,所以在Unity5.3以上版本開始原生提供Json的解析API,如下圖:
對於Json 的初學者,為了更好的理解後面的配置管理技術講解,特提供使用Unity的API 對Json 配置文件的解析示例:
Json基本解析示例
- 示例1:
對於Unity 原生支持Json 解析方法的最簡測試演示。
1 namespace Test 2 { 3 [Serializable] 4 public class Hero 5 { 6 //名稱 7 public string Name; 8 //等級 9 public Level MyLevel; 10 11 } 12 } 13 14 namespace Test 15 { 16 [Serializable] 17 public class Level 18 { 19 public int HeroLevel; 20 21 } 22 }View Code
1 /*** 2 * 3 * Title: "SUIFW" UI框架項目 4 * 主題: 演示Unity 對Json 解析API 5 6 using System.Collections; 7 using System.Collections.Generic; 8 using UnityEngine; 9 10 namespace Test 11 { 12 public class TestUnityJson : MonoBehaviour { 13 14 15 void Start () { 16 Hero heroObj=new Hero(); 17 heroObj.Name = "郭靖"; 18 heroObj.MyLevel = new Level() {HeroLevel = 800}; 19 //相當於如下寫法 20 //Level lev=new Level(); 21 //lev.HeroLevel = 800; 22 //heroObj.MyLevel = lev; 23 24 //方法1: Json 序列化工作(對象--> 文件) 25 string strHeroInfo = JsonUtility.ToJson(heroObj); 26 Debug.Log("測試1: 得到的序列化後的字符串="+strHeroInfo); 27 28 //方法2: 反序列化(Json文件--> 對象) 29 Hero heroInfo2 = JsonUtility.FromJson<Hero>(strHeroInfo); 30 Debug.Log("測試2:得到反序列化對象數值,名稱: "+heroInfo2.Name+" 等級: "+heroInfo2.MyLevel.HeroLevel); 31 32 //方法3: 測試覆蓋反序列化。 33 Hero hero=new Hero(); 34 hero.Name = "楊過"; 35 hero.MyLevel = new Level() {HeroLevel = 500}; 36 37 //Json 序列化 38 string heroInfo3 = JsonUtility.ToJson(hero); 39 //測試覆蓋反序列化 40 JsonUtility.FromJsonOverwrite(heroInfo3, heroObj); 41 Debug.Log("測試3, 得到再次反序列化覆蓋的對象信息,名稱: "+heroObj.Name+" 等級: "+heroObj.MyLevel.HeroLevel); 42 43 44 } 45 46 } 47 }View Code
- 示例2:
對於Json 文件的實戰性測試用例演示。
1 /*** 2 * 3 * Title: "SUIFW" UI框架項目 4 * 主題: 對於Unity中Resource 目錄下的Json 文件的解析Demo 5 * Description: 6 * 功能: yyy 7 * 8 * Date: 2017 9 * Version: 0.1版本 10 * Modify Recoder: 11 * 12 * 13 */ 14 using System.Collections; 15 using System.Collections.Generic; 16 using UnityEngine; 17 18 namespace Test 19 { 20 public class TestUnityJson2 : MonoBehaviour { 21 22 23 void Start () 24 { 25 //提取文件,得到字符串數據 26 TextAsset TaObj=Resources.Load<TextAsset>("People"); 27 //反序列化 文件-->對象 28 PersonInfo perInfo=JsonUtility.FromJson<PersonInfo>(TaObj.text); 29 //顯示對象中數據 30 foreach (People per in perInfo.People) 31 { 32 Debug.Log(" "); 33 Debug.Log(string.Format("name={0},Age={1}",per.Name,per.Age)); 34 } 35 } 36 37 } 38 }View Code
以上代碼解釋如下:
Unity(5.3以上版本)提供的JsonUtility 提供了三個重要方法
JsonUtility.ToJson() //表示進行序列化操作,把對象序列化為字符串。
JsonUtility.FromJson() ;//表示進行反序列化操作,把Json字符串反序列化為對象。
JsonUtility.FromJsonOverwrite();//是覆蓋方式進行反序列化。
有了以上技術儲備,我們就可以進行開發“通用配置管理器”了。
第1步: 首先定義通用配置管理器接口與輔助類。
代碼如下:
1 /*** 2 * 3 * Title: "SUIFW" UI框架項目 4 * 主題: 通用配置管理器接口 5 * Description: 6 * 功能: 7 * 基於“鍵值對”配置文件的通用解析 8 * 9 * Date: 2017 10 * Version: 0.1版本 11 * Modify Recoder: 12 * 13 * 14 */ 15 16 using System; 17 using System.Collections; 18 using System.Collections.Generic; 19 using UnityEngine; 20 21 namespace SUIFW 22 { 23 public interface IConfigManager { 24 25 /// <summary> 26 /// 只讀屬性: 應用設置 27 /// 功能: 得到鍵值對集合數據 28 /// </summary> 29 Dictionary<string, string> AppSetting { get; } 30 31 /// <summary> 32 /// 得到配置文件(AppSeting)最大的數量 33 /// </summary> 34 /// <returns></returns> 35 int GetAppSettingMaxNumber(); 36 37 } 38 39 [Serializable] 40 internal class KeyValuesInfo 41 { 42 //配置信息 43 public List<KeyValuesNode> ConfigInfo = null; 44 } 45 46 [Serializable] 47 internal class KeyValuesNode 48 { 49 //鍵 50 public string Key = null; 51 //值 52 public string Value = null; 53 } 54 }View Code
第2步: 定義Json 解析異常類。
Json 的解析過程如果出錯,推薦使用我們自己定義的異常處理,為了更好的發現程序錯誤,所以自定義Json 解析異常類定義如下:
1 /*** 2 * 3 * Title: "SUIFW" UI框架項目 4 * 主題: Json 解析異常 5 * Description: 6 * 功能:專門負責對於JSon 由於路徑錯誤,或者Json 格式錯誤造成的異常,進行捕獲。 7 * 8 * Date: 2017 9 * Version: 0.1版本 10 * Modify Recoder: 11 * 12 * 13 */ 14 15 using System; 16 using System.Collections; 17 using System.Collections.Generic; 18 using UnityEngine; 19 20 namespace SUIFW 21 { 22 public class JsonAnlysisException : Exception { 23 public JsonAnlysisException() : base(){} 24 public JsonAnlysisException(string exceptionMessage) : base(exceptionMessage){} 25 } 26 }View Code
第3步:定義“配置管理器”類
開發實現IConfigManager 接口的通用配置管理器
1 /*** 2 * 3 * Title: "SUIFW" UI框架項目 4 * 主題:基於Json 配置文件的“配置管理器” 5 * Description: 6 * 功能: 7 * 8 * Date: 2017 9 * Version: 0.1版本 10 * Modify Recoder: 11 * 12 * 13 */ 14 15 using System; 16 using System.Collections; 17 using System.Collections.Generic; 18 using UnityEngine; 19 20 namespace SUIFW 21 { 22 public class ConfigManagerByJson : IConfigManager 23 { 24 //保存(鍵值對)應用設置集合 25 private static Dictionary<string, string> _AppSetting; 26 27 /// <summary> 28 /// 只讀屬性: 得到應用設置(鍵值對集合) 29 /// </summary> 30 public Dictionary<string, string> AppSetting 31 { 32 get { return _AppSetting; } 33 } 34 35 /// <summary> 36 /// 構造函數 37 /// </summary> 38 /// <param name="jsonPath">Json配置文件路徑</param> 39 public ConfigManagerByJson(string jsonPath) 40 { 41 _AppSetting=new Dictionary<string, string>(); 42 //初始化解析Json 數據,加載到(_AppSetting)集合。 43 InitAndAnalysisJson(jsonPath); 44 } 45 46 /// <summary> 47 /// 得到AppSetting 的最大數值 48 /// </summary> 49 /// <returns></returns> 50 public int GetAppSettingMaxNumber() 51 { 52 if (_AppSetting!=null && _AppSetting.Count>=1) 53 { 54 return _AppSetting.Count; 55 } 56 else 57 { 58 return 0; 59 } 60 } 61 62 /// <summary> 63 /// 初始化解析Json 數據,加載到集合眾。 64 /// </summary> 65 /// <param name="jsonPath"></param> 66 private void InitAndAnalysisJson(string jsonPath) 67 { 68 TextAsset configInfo = null; 69 KeyValuesInfo keyvalueInfoObj = null; 70 71 //參數檢查 72 if (string.IsNullOrEmpty(jsonPath)) return; 73 //解析Json 配置文件 74 try{ 75 configInfo = Resources.Load<TextAsset>(jsonPath); 76 keyvalueInfoObj=JsonUtility.FromJson<KeyValuesInfo>(configInfo.text); 77 } 78 catch{ 79 throw new JsonAnlysisException(GetType() + "/InitAndAnalysisJson()/Json Analysis Exception ! Parameter jsonPath=" + jsonPath); 80 } 81 //數據加載到AppSetting 集合中 82 foreach (KeyValuesNode nodeInfo in keyvalueInfoObj.ConfigInfo) 83 { 84 _AppSetting.Add(nodeInfo.Key,nodeInfo.Value); 85 } 86 } 87 88 89 90 } 91 }View Code
代碼說明:
以上定義的“配置管理器”,可以對所有具備“鍵值對”特性的Json 配置文件,做統一數據提取工作,從而對於“UI預設”、“遊戲對象”、“日誌配置文件”、“語言國際化”等信息,可以做統一處理,極大提供開發效率。以下筆者提供本UI框架需要用到的除企業日誌系統外,其他兩種配置文件的截圖,供參考。
(企業級Log日誌中使用到的配置信息)
(“UI預設” 路徑信息Json配置文件)
本篇就先寫到這,下篇 "遊戲UI框架設計(6)_消息傳遞中心" 繼續。
遊戲UI框架設計(五): 配置管理與應用