60.自定义协议工具生成枚举

60.消息处理-自定义协议生成工具-协议消息生成-生成枚举


60.1 知识点

协议消息生成主要做什么?

  • 协议生成:主要是使用配置文件中读取出来的信息,动态生成对应语言的代码文件。
  • 作用:每次添加消息或者数据结构类时,我们不需要再手写代码了。我们不仅可以生成 C# 脚本文件,还可以根据需求生成别的语言的文件。

制作功能前的准备工作

  • 协议生成:不会在发布后使用的功能,主要是在开发时使用。
  • 实现方式:在 Unity 中将其作为一个编辑器功能来实现,可以专门新建一个 Editor 文件夹(专门放编辑器相关内容,不会发布),在其中放置配置文件和自动生成相关脚本文件。

把上一节课的 xml 文件改名成 ProtocolInfo.xml 放到 Editor 文件夹下

创建 ProtocolTool 类,放在 Editor 文件夹下,类中定义 xml 配置文件所在的路径,加入特性使编辑器中出现生成脚本的按钮

public class ProtocolTool
{
    // 配置文件所在路径
    private static string PROTO_INFO_PATH = Application.dataPath + "/Editor/ProtocolTool/ProtocolInfo.xml";

    [MenuItem("ProtocolTool/生成C#脚本")]
    private static void GenerateCSharp()
    {
        Debug.Log("生成C#代码");
    }

    [MenuItem("ProtocolTool/生成C++脚本")]
    private static void GenerateC()
    {
        Debug.Log("生成C++代码");
    }

    [MenuItem("ProtocolTool/生成Java脚本")]
    private static void GenerateJava()
    {
        Debug.Log("生成Java代码");
    }
}

制作生成枚举功能

ProtocolTool 类中定义读取 xml 相关信息的方法

/// <summary>
/// 获取指定名字的所有子节点的 List
/// </summary>
/// <param name="nodeName"></param>
/// <returns></returns>
private static XmlNodeList GetNodes(string nodeName)
{
    XmlDocument xml = new XmlDocument();
    xml.Load(PROTO_INFO_PATH);
    XmlNode root = xml.SelectSingleNode("messages");
    return root.SelectNodes(nodeName);
}

定义 GenerateCSharp 类,专门用于生成 C# 代码。定义协议保存路径。之后这个类会写生成枚举,数据结构类,消息类的逻辑。

public class GenerateCSharp
{
    // 协议保存路径
    private string SAVE_PATH = Application.dataPath + "/Scripts/Protocol/";

    // 生成枚举
    public void GenerateEnum(XmlNodeList nodes)
    {
    } 

    // 生成数据结构类

    // 生成消息类
}

在 ProtocolTool 类定义静态 GenerateCSharp 类对象。生成 C# 脚本的方法中调用 GenerateCSharp 类对象生成枚举函数,传入所有的枚举 xml 节点列表。

private static GenerateCSharp generateCSharp = new GenerateCSharp();

[MenuItem("ProtocolTool/生成C#脚本")]
private static void GenerateCSharp()
{
    // 读取 xml 相关的信息
    // XmlNodeList list = GetNodes("enum");
    // 根据这些信息 去拼接字符串 生成对应的脚本 
    generateCSharp.GenerateEnum(GetNodes("enum"));

    // 刷新编辑器界面 让我们可以看到生成的内容 不需要手动进行刷新了
    AssetDatabase.Refresh();
}

观察自己声明的枚举类应该怎么拼接,等一下照着拼

namespace GamePlayer
{
    public enum E_PLAYER_TYPE
    {
        // 枚举字段
        MAIN = 1,
        OTHER,
    }
}

根据枚举相关信息实现 GenerateCSharp 类的生成枚举函数,拼接字符串,生成枚举脚本文件

// 生成枚举
public void GenerateEnum(XmlNodeList nodes)
{
    // 生成枚举脚本的逻辑
    string namespaceStr = "";
    string enumNameStr = "";
    string fieldStr = "";

    foreach (XmlNode enumNode in nodes)
    {
        // 获取命名空间配置信息
        namespaceStr = enumNode.Attributes["namespace"].Value;

        // 获取枚举名配置信息
        enumNameStr = enumNode.Attributes["name"].Value;

        // 获取所有的字段节点 然后进行字符串拼接
        XmlNodeList enumFields = enumNode.SelectNodes("field");

        // 一个新的枚举 需要清空一次上一次拼接的字段字符串
        fieldStr = "";

        foreach (XmlNode enumField in enumFields)
        {
            fieldStr += "\t\t" + enumField.Attributes["name"].Value;
            if (enumField.InnerText != "")
                fieldStr += " = " + enumField.InnerText;
            fieldStr += ",\r\n";
        }

        // 对所有可变的内容进行拼接
        string enumStr = $"namespace {namespaceStr}\r\n" +
                         "

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏