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

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

oid per b- 測試 中心 序列化對象 ner stun sage

遊戲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框架設計(五): 配置管理與應用