59.消息处理-自定义协议生成工具-协议消息配置
59.1 知识点
选择哪种格式配置协议?
- xmlDocument
- json
- excel
- 自定义
- 等等
我们可以根据自己的喜好选择,选择方便配置的,好用的即可。配置的主要目的是确定类名、成员变量名。之后根据读取的这些配置信息,再通过代码按照规则自动生成对应的类文件。
我个人喜欢使用xml作为协议配置文件。学会xml配置,其它的方式都是大同小异的。我们主要是学习制作思路和流程。以后的项目中,大家根据自己的喜好选择即可。
以xml配置为例制定配置规则
主要步骤
- xml相关知识:可以在数据持久化之xml中进行学习
- 创建xml配置文件
- 制定配置规则
- 枚举规则
- 数据类规则
- 消息类规则
配置完成后的xml文件
<?xml version="1.0" encoding="UTF-8"?>
<messages>
<!--枚举配置规则 包含 枚举名 命名空间 枚举字段名 可能包含枚举字段值-->
<enum name="E_PLAYER_TYPE" namespace="GamePlayer">
<field name="MAIN">1</field>
<field name="OTHER"/>
</enum>
<enum name="E_HERO_TYPE" namespace="GamePlayer">
<field name="MAIN"/>
<field name="OTHER"/>
</enum>
<enum name="E_MONSTER_TYPE" namespace="GameMonster">
<field name="NORMAL">2</field>
<field name="BOSS"/>
</enum>
<!--数据结构类配置规则 包含 类名 命名空间 变量类型 变量名-->
<data name="PlayerData" namespace="GamePlayer">
<field type="int" name="id"/>
<field type="float" name="atk"/>
<field type="bool" name="sex"/>
<field type="long" name="lev"/>
<field type="array" data="int" name="arrays"/>
<field type="list" T="int" name="list"/>
<field type="dic" Tkey="int" Tvalue="string" name="dic"/>
<field type="enum" data="E_HERO_TYPE" name="heroType"/>
</data>
<data name="HeartData" namespace="GameSystem">
<field type="long" name="time"/>
</data>
<!--消息类类配置规则 包含 消息ID 类名 命名空间 变量类型 变量名-->
<message id="1001" name="PlayerMessage" namespace="GamePlayer">
<field type="int" name="playerID"/>
<field type="PlayerData" name="data"/>
</message>
<message id="1002" name="HeartMessage" namespace="GameSystem"/>
</messages>
读取xml配置信息
读取xml文件信息
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(Application.dataPath + "/网络基础教程/Lesson59_消息处理_自定义协议生成工具_协议消息配置/Lesson59_消息处理_自定义协议生成工具_协议消息配置.xml");
读取各节点元素
根节点读取
// 获取XML文档中名为 "messages" 的根节点
XmlNode rootXmlNode = xmlDocument.SelectSingleNode("messages");
读取出所有枚举结构类节点
print("******枚举******");
// 获取名为 "enum" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList enumXmlNodeList = rootXmlNode.SelectNodes("enum");
// 遍历所有 "enum" 子节点
foreach (XmlNode enumXmlNode in enumXmlNodeList)
{
print("**************");
// 打印枚举的名称
print("枚举名字:" + enumXmlNode.Attributes["name"].Value);
// 打印枚举所在的命名空间
print("枚举所在命名空间:" + enumXmlNode.Attributes["namespace"].Value);
print("******枚举成员字段******");
// 获取该枚举节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = enumXmlNode.SelectNodes("field");
// 遍历枚举的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
string str = fieldXmlNode.Attributes["name"].Value;
// 如果枚举字段具有值,则将其添加到输出字符串
if (fieldXmlNode.InnerText != "")
str += " = " + fieldXmlNode.InnerText;
str += ",";
// 打印枚举字段的名称和可能的值
print(str);
}
print("**************");
}
读取出所有数据结构类节点
print("******数据结构类******");
// 获取名为 "data" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList dataXmlNodeList = rootXmlNode.SelectNodes("data");
// 遍历所有 "data" 子节点
foreach (XmlNode dataXmlNode in dataXmlNodeList)
{
print("**************");
// 打印数据结构类的名称
print("数据结构类名:" + dataXmlNode.Attributes["name"].Value);
// 打印数据结构类所在的命名空间
print("数据结构类所在命名空间:" + dataXmlNode.Attributes["namespace"].Value);
print("******数据结构类成员******");
// 获取该数据结构类节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = dataXmlNode.SelectNodes("field");
// 遍历数据结构类的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
// 获取字段的数据类型和名称,然后打印
print(fieldXmlNode.Attributes["type"].Value + " " + fieldXmlNode.Attributes["name"].Value + ";");
}
print("**************");
}
读取出所有消息节点
print("******消息类******");
// 获取名为 "message" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList messageXmlNodeList = rootXmlNode.SelectNodes("
message");
// 遍历所有 "message" 子节点
foreach (XmlNode messageXmlNode in messageXmlNodeList)
{
print("**************");
// 打印消息类的名称
print("消息类名:" + messageXmlNode.Attributes["name"].Value);
// 打印消息类所在的命名空间
print("消息类所在命名空间:" + messageXmlNode.Attributes["namespace"].Value);
// 打印消息ID
print("消息ID:" + messageXmlNode.Attributes["id"].Value);
print("******消息类成员******");
// 获取该消息类节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = messageXmlNode.SelectNodes("field");
// 遍历消息类的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
// 获取字段的数据类型和名称,然后打印
print(fieldXmlNode.Attributes["type"].Value + " " + fieldXmlNode.Attributes["name"].Value + ";");
}
print("**************");
}
总结
利用配置文件配置消息、数据结构、枚举的目的:
- 减少工作量,配置一次,之后自动化生成各种语言对应的类文件。
- 减少沟通成本,避免前后端语言不同时,手动写代码出现前后端不统一的问题。
59.2 知识点代码
Lesson59_消息处理_自定义协议生成工具_协议消息配置
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;
public class Lesson59_消息处理_自定义协议生成工具_协议消息配置 : MonoBehaviour
{
void Start()
{
#region 知识点一 选择哪种格式配置协议?
//1.xmlDocument
//2.json
//3.excel
//4.自定义
//等等
//我们可以根据自己的喜好选择
//选择方便配置的,好用的即可
//配置的主要目的是确定
//类名、成员变量名
//之后根据读取的这些配置信息
//再通过代码按照规则自动生成对应的类文件
//我个人喜欢使用xml作为协议配置文件
//学会xml配置,其它的方式都是大同小异的
//我们主要是学习制作思路和流程
//以后的项目中,大家根据自己的喜好选择即可
#endregion
#region 知识点二 以xml配置为例制定配置规则
//xml相关知识,可以在数据持久化之xml中进行学习
//1. 创建xml配置文件
//2. 制定配置规则
// 1.枚举规则
// 2.数据类规则
// 3.消息类规则
#endregion
#region 知识点三 读取xml配置信息
//1.读取xml文件信息
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(Application.dataPath + "/网络基础教程/Lesson59_消息处理_自定义协议生成工具_协议消息配置/Lesson59_消息处理_自定义协议生成工具_协议消息配置.xml");
//2.读取各节点元素
//2-1: 根节点读取
// 获取XML文档中名为 "messages" 的根节点
XmlNode rootXmlNode = xmlDocument.SelectSingleNode("messages");
//2-2: 读取出所有枚举结构类节点
print("******枚举******");
// 获取名为 "enum" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList enumXmlNodeList = rootXmlNode.SelectNodes("enum");
// 遍历所有 "enum" 子节点
foreach (XmlNode enumXmlNode in enumXmlNodeList)
{
print("**************");
// 打印枚举的名称
print("枚举名字:" + enumXmlNode.Attributes["name"].Value);
// 打印枚举所在的命名空间
print("枚举所在命名空间:" + enumXmlNode.Attributes["namespace"].Value);
print("******枚举成员字段******");
// 获取该枚举节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = enumXmlNode.SelectNodes("field");
// 遍历枚举的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
string str = fieldXmlNode.Attributes["name"].Value;
// 如果枚举字段具有值,则将其添加到输出字符串
if (fieldXmlNode.InnerText != "")
str += " = " + fieldXmlNode.InnerText;
str += ",";
// 打印枚举字段的名称和可能的值
print(str);
}
print("**************");
}
//2-3: 读取出所有数据结构类节点
print("******数据结构类******");
// 获取名为 "data" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList dataXmlNodeList = rootXmlNode.SelectNodes("data");
// 遍历所有 "data" 子节点
foreach (XmlNode dataXmlNode in dataXmlNodeList)
{
print("**************");
// 打印数据结构类的名称
print("数据结构类名:" + dataXmlNode.Attributes["name"].Value);
// 打印数据结构类所在的命名空间
print("数据结构类所在命名空间:" + dataXmlNode.Attributes["namespace"].Value);
print("******数据结构类成员******");
// 获取该数据结构类节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = dataXmlNode.SelectNodes("field");
// 遍历数据结构类的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
// 获取字段的数据类型和名称,然后打印
print(fieldXmlNode.Attributes["type"].Value + " " + fieldXmlNode.Attributes["name"].Value + ";");
}
print("**************");
}
//2-4: 读取出所有消息节点
print("******消息类******");
// 获取名为 "message" 的所有子节点并存储在 XmlNodeList 中
XmlNodeList messageXmlNodeList = rootXmlNode.SelectNodes("message");
// 遍历所有 "message" 子节点
foreach (XmlNode messageXmlNode in messageXmlNodeList)
{
print("**************");
// 打印消息类的名称
print("消息类名:" + messageXmlNode.Attributes["name"].Value);
// 打印消息类所在的命名空间
print("消息类所在命名空间:" + messageXmlNode.Attributes["namespace"].Value);
// 打印消息ID
print("消息ID:" + messageXmlNode.Attributes["id"].Value);
print("******消息类成员******");
// 获取该消息类节点下所有名为 "field" 的子节点
XmlNodeList fieldXmlNodeList = messageXmlNode.SelectNodes("field");
// 遍历消息类的成员字段
foreach (XmlNode fieldXmlNode in fieldXmlNodeList)
{
// 获取字段的数据类型和名称,然后打印
print(fieldXmlNode.Attributes["type"].Value + " " + fieldXmlNode.Attributes["name"].Value + ";");
}
print("**************");
}
#endregion
#region 总结
//利用配置文件配置消息、数据结构、枚举的目的
//1.减少工作量,配置一次,之后自动化生成各种语言对应的类文件
//2.减少沟通成本,避免前后端语言不同时,手动写代码出现前后端不统一的问题
#endregion
}
}
Lesson59_消息处理_自定义协议生成工具_协议消息配置.xml
<?xml version="1.0" encoding="UTF-8"?>
<messages>
<!--枚举配置规则 包含 枚举名 命名空间 枚举字段名 可能包含枚举字段值-->
<enum name="E_PLAYER_TYPE" namespace="GamePlayer">
<field name="MAIN">1</field>
<field name="OTHER"/>
</enum>
<enum name="E_HERO_TYPE" namespace="GamePlayer">
<field name="MAIN"/>
<field name="OTHER"/>
</enum>
<enum name="E_MONSTER_TYPE" namespace="GameMonster">
<field name="NORMAL">2</field>
<field name="BOSS"/>
</enum>
<!--数据结构类配置规则 包含 类名 命名空间 变量类型 变量名-->
<data name="PlayerData" namespace="GamePlayer">
<field type="int" name="id"/>
<field type="float" name="atk"/>
<field type="bool" name="sex"/>
<field type="long" name="lev"/>
<field type="array" data="int" name="arrays"/>
<field type="list" T="int" name="list"/>
<field type="dic" Tkey="int" Tvalue="string" name="dic"/>
<field type="enum" data="E_HERO_TYPE" name="heroType"/>
</data>
<data name="HeartData" namespace="GameSystem">
<field type="long" name="time"/>
</data>
<!--消息类类配置规则 包含 消息ID 类名 命名空间 变量类型 变量名-->
<message id="1001" name="PlayerMessage" namespace="GamePlayer">
<field type="int" name="playerID"/>
<field type="PlayerData" name="data"/>
</message>
<message id="1002" name="HeartMessage" namespace="GameSystem"/>
</messages>
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com