UE4 接入 Protobuf(C++ 层)

引言

在网络游戏开发中,我们通常使用 Google Protobuf 作为网络协议定制的格式,那么在 UE4 中如何集成 Protobuf 是我们接下来要做的事情。

 

开源示例

看过很多篇文章,但这篇是写的最详细的 在UnrealEngine4中使用Google Protobuf ,对应的 Github 工程 jashking/UE4Protobuf

 

基本步骤

1. 库文件导入

直接从下面下载的 jashking/UE4Protobuf 这个 demo 工程中复制即可:

  • Source/Protobuf 库当做一个模块引入到自己的 UE4 工程中,放在工程目录下的 Source/Protobuf 目录

  • 在工程的 工程名称.Build.cs 中添加该模块的引用:

    PrivateDependencyModuleNames.AddRange(new string[] { 
        ...
        "Protobuf" 
    });

    同时还需要添加一些预防 Protobuf 内容引入导致报错的配置:

    // Protobuf source integrationg
    bEnableShadowVariableWarnings = false;
    bEnableUndefinedIdentifierWarnings = false;
    bEnableExceptions = true;
    ​
    if (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64)
    {
        Definitions.Add("_CRT_SECURE_NO_WARNINGS");
    }

2. 协议转化

这里我简单编写了一个可以自动转化协议文件的批处理(BAT)工具脚本:

  • 复制并使用 Source/Protobuf/bin 目录中的 protoc.exe 工具,将改工具放在协议同级目录下;

  • 然后,遍历所有的协议文件,将每个 .proto 协议文件转为对应的 .cc.h 脚本,使用一个自动化脚本(如:BAT批处理)

    set PROTO_PATH=.\Protocol
    set STEP1_PROTO2CPP_PATH=.\step1_proto2cpp
    ​
    cd %STEP1_PROTO2CPP_PATH%
    ​
    dir ..\%PROTO_PATH%\*.proto /b  > protolist.txt
    ​
    for /f "delims=." %%i in (protolist.txt) do protoc --cpp_out=. --proto_path=..\%PROTO_PATH% ..\%PROTO_PATH%\%%i.proto 

    每个 .proto 文件会生成 .pb.cc.pb.h 文件

  • 然后都复制到工程模块中,其中 .cc 复制到 Private 目录(顺便修改后缀名为 .cpp),.h 复制到 Public 目录:

    set OUT_PATH=..\Source
    set CPP_DEST=ThirdParty\Protobuf\Private
    set HEAD_DEST=ThirdParty\Protobuf\Public
    ​
    copy %STEP1_PROTO2CPP_PATH%\*.pb.cc %OUT_PATH%\%CPP_DEST%\*.pb.cpp
    copy %STEP1_PROTO2CPP_PATH%\*.pb.h %OUT_PATH%\%HEAD_DEST%\*.pb.h
  • 在需要使用的地方,除了协议对应的头文件外,还需要引入两个额外的头文件

    #include "协议文件.pb.h"

     

测试实例

1. 定义协议文件

测试 login.proto :

syntax = "proto3";
package csprotos;
​
//登陆
message LoginReq
{
    optional uint32 AppID = 10;
    optional string UserName = 11;
}

按照上述,使用自动化工具将 .proto 文件转化生成 .cpp 和 .h 。

 

2. 创建测试脚本

这里我们直接创建一个自定义的 GameInstance 类作为测试脚本,步骤如下:

  • 在菜单 File —> New C++ Class...

  • 勾选 Show All Classes ,搜索 GameInstance ,即可自定义一个继承自 GameInstance 的类 MyCustomGameInstance

编写如下测试代码:

  • MyCustomGameInstance.h

    // Fill out your copyright notice in the Description page of Project Settings.
    ​
    #pragma once
    ​
    #include "CoreMinimal.h"
    #include "Engine/GameInstance.h"
    #include "MyCustomGameInstance.generated.h"
    ​
    /**
     * 
     */
    UCLASS()
    class BLUEEMPTY_API UMyCustomGameInstance : public UGameInstance
    {
        GENERATED_BODY()
        
    public:
        UMyCustomGameInstance();
    };
  • MyCustomGameInstance.cpp

    // Fill out your copyright notice in the Description page of Project Settings.
    ​
    #include "MyCustomGameInstance.h"
    #include "BlueEmpty.h"
    ​
    #include "ProtocolGen/login.pb.h"
    // 与 proto 中定义的 package 对应
    using namespace csprotos;
    ​
    UMyCustomGameInstance::UMyCustomGameInstance() 
    {
        UE_LOG(LogTemp, Display, TEXT("--------------- Protobuf Test"));
        LoginReq req;
        req.set_appid(666);
        req.set_username("linsh");
        // 序列化
        const std::string msg = req.SerializeAsString();
        // 反序列化
        LoginReq req1;
        req1.ParseFromString(msg);
        
        FString nameAsFString = req1.username().c_str();
        UE_LOG(LogTemp, Display, TEXT("----- req1: appid = %d, username = %s"), req1.appid(), *nameAsFString);
    }

编写完代码后回到 UE4 中,点击 Compile 按钮编译新增的代码,然后在 Project Settings 中指定自定义的 MyCustomGameInstance 类作为工程的 GameInstance 类:

  • 打开项目设置界面:Settings—>Project Settings

  • 选择 Project\Maps & Modes 设置项,滚动至最底部就是 GameInstance 类的设置项:

 

运行结果

然后运行,在输出日志窗口中可以看到如下输出:

LogTemp: Display: --------------- Protobuf Test
LogTemp: Display: ----- req1: appid = 666, username = linsh

注意,不能用 UE_LOG 指定打印 std::string 类型的字符串,需要先通过 c_str() 接口转为 FString 类型再进行打印

 

打开输出日志窗口

假如日志窗口未打开,可以通过菜单 Window —> Developer Tools —> Output Log 打开

 

小结

以这种方式接入 Protobuf 的话,协议文件无法通过热更进行修改,后面打算接入腾讯开源的 UnLua ,然后在 Lua 层接入 Protobuf ,从而达到热更协议的目的。

 

参考

已标记关键词 清除标记
1、本课程是一个干货课程,主要讲解如何封装服务器底层,使用Tcp/ip长连接,IDE使用vs2019 c++开发以及使用c++11的一些标准,跨平台windows和linux,服务器性能高效,单服务器压力测试上万无压力,服务器框架是经历过上线产品的验证,框架简单明了,不熟悉底层封装的人,半个小时就能完全掌握服务器框架上手写业务逻辑。 2、本课程是一个底层服务器框架教程,主要是教会学员在windows或linux下如何封装一个高效的,避免踩坑的商业级框架,服务器底层使用初始化即开辟内存的技术,使用内存池,服务器运行期间内存不会溢出,非常稳定,同时服务器使用自定义哈希hashContainer,在处理新的连接,新的数据,新的封包,以及解包,发包,粘包的过程,哈希容器性能非常高效,增、删、查、改永远不会随着连接人数的上升而降低性能,增、删、查、改的复杂度永远都是恒定的O(1)。 3、服务器底层封装没有使用任何第三方网络库以及任何第三方插件,自由度非常的高,出了任何BUG,你都有办法去修改,查找问题也非常方便,在windows下使用iocp,linux下使用epoll. 4、讲解c++纯客户端,主要用于服务器之间通信,也就是说你想搭建多层结构的服务器,服务器与服务器之间使用socket通信。还可以使用c++客户端做压力测试,开辟多线程连接服务器,教程提供了压力测试,学员可以自己做压力测试服务器性能。 5、赠送ue4和unity3d通信底层框架以及多人交互demo,登录,注册,玩家离开,同步主要是教会学员服务器与客户端如何交互。 6、赠送c++连接mysql数据库框架demo,登录,注册,玩家离开数据持久化. 7、服务器教程使用自定义通信协议,同时也支持protobuf,选择权在开发者自己手里,想用什么协议都可以,自由度高。 8、服务器教程使用手动敲代码逐句讲解的方式开展教学课程。非喜勿喷,谢谢大家。 9、服务器教程提供源码,大家可以在平台提供的地址下载或者联系我,服务器使用c++11部分标准,std::thread,条件变量,线程锁,智能指针等,需要学员具备一定c++知识,购买前请慎重考虑。
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页