• 游戏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)_消息传递中心" 继续。

  • 相关阅读:
    Kotlin Coroutines不复杂, 我来帮你理一理
    Refresh design pattern
    Android App安装包瘦身计划
    Google IO 2019 Android 太长不看版
    Effective Java读书笔记完结啦
    探究高级的Kotlin Coroutines知识
    移动应用中的非功能性(跨职能)需求
    Android程序员的Flutter学习笔记
    如何正确使用Espresso来测试你的Android程序
    MVP模式, 开源库mosby的使用及代码分析
  • 原文地址:https://www.cnblogs.com/LiuGuozhu/p/6943284.html
Copyright © 2020-2023  润新知