你需要同款“Unreal项目自动化编译、打包和部署”方案吗?
在过往几期的UWA Pipeline最佳实践案例中,我们分享了如何通过Pipeline实现性能优化、性能管理、游戏内容验收和云真机系统的应用(实现批量真机设备的自动化测试,以及针对特效性能优化的方式),其实这些高效的方法并不局限游戏引擎。今天,分享一篇来自广州钛壳树的UWA Pipeline使用心得,这是一家致力于创造独特原创IP、专注Unreal研发的游戏公司,看看UWA Pipeline如何帮助Unreal研发团队达到如虎添翼的效果。
常态化的引擎自动化编译、客户端自动打包、服务器持续部署,这是钛壳树团队在Unreal项目研发的过程中,使用UWA Pipeline实现的三大功能,大幅简化了工作流程,节省了人力与时间,提高了CI/CD的执行效率。以下分享出自钛壳树团队CEO的自述,详细介绍了具体实现的思路和方式,供广大有类似需求的Unreal团队参考。
一、Unreal引擎自动编译的实现
我们使用Windows作为流水线节点,通过流水线的简单操作,快速有效地实现不同的构建需求;通常UE引擎都有比较严格的运行环境和编译条件,借助流水线和联合编译IncrediBuild能极大提高构建效率,降低构建复杂度,减少人工干预的次数。
研发过程中修改Unreal引擎源码是必不可少的。获取源码后,除了有利于理解引擎的运行机制和方便调试,更多的是可以对引擎进行个性化定制,从而增强项目的游戏效果和可玩性。在构建流水线之前,大家可以通过Pipeline设置中的环境变量,来预设工作目录和工程路径,方便在后续的步骤中调用。

我们的引擎编译流水线如下图所示,主要包括“Init”、“UpdateRepos”、“BuildAndCook” 和“CommitRepos”四个阶段。

每个阶段的具体作用为:
第一阶段 Init
确保编译环境干净、当前任务独占相关资源。如此运算力资源能够充分利用,并且可以避免资源占用冲突导致的报错。我们的做法是:初始化环境、确保没有手动打开的编译进程。同时将节点的并发构建数量设置为1,确保不会有多个任务并发执行。
第二阶段 UpdateRepos
进入预设的工作目录,通过Git和凭证管理,更新位于内部Gitlab的引擎源码ue_tree。

第三阶段 BuildAndCook
编译引擎。进入工作目录调用VisualStudio编译命令,对引擎工程进行命令行编译,对应的批处理脚本如下:

通常编译引擎会占用很多CPU算力资源,需要花费很长时间才能完成编译,所以非必要情况下不执行Rebuild操作。我们在这里通过Pipeline的参数化构建功能,在流水线上设定选项参数,提供多种编译方式(Build和Rebuild),在执行时,就可以将参数传递给编译器以明确编译模式。

第四阶段 CommitRepos
把最新的引擎提交到SVN,用于接下来的开发任务。引擎编译后会生成若干目录,其中包含引擎运行所需的DLL、执行程序以及中间文件。这里大家需要区分中间文件的内容,避免把不必要的文件上传到SVN仓库中。

二、Unreal客户端自动打包的实现
完成引擎编译后,接下来就是对游戏客户端进行编译打包。日常的持续构建,能够方便我们随时跟进游戏研发进度,体验游戏的特性和玩法。Unreal客户端打包时,大家需要注意引擎版本的使用,将官方版本和自定义版本区别开,以免效果不符合预期。
我们的打包流水线如下图所示,主要包括“Init”、“UpdateRepos”、“StartBuild”、“BuildAndCook”和“Commit”五个阶段。

每个阶段的具体作用为:
第一阶段 Init
与编译引擎的处理方式一致,确保任务独占编译资源,保证后续步骤顺利进行。
第二阶段 UpdateRepos
获取最新的代码和资源。游戏客户端除了涉及开发代码和脚本外,还需要有数据资源,包括蓝图、配置数据、材质、模型、场景等等。其中代码和脚本使用Gitlab管理,数据资源使用SVN管理。

在打包的时候,大家需要再创建一个新的工作目录,把最新获取的代码和资源都拷贝到工作目录中,进行独立编译。

第三阶段 StartBuild
执行编译前的准备工作。
设定工程使用的引擎版本,在开发时是通过右键菜单进行选择,在流水线中则使用VersionSelector.exe命令处理。

选择引擎后需要对工程生成对应的编译工具,包括:UnrealPak、Bootstrap、CrashReport以及工程,命令如下。

第四阶段 BuildAndCook
将游戏工程生成最终能运行的程序或安装包。其中,Build执行的是针对所选平台编译二进制可执行文件;Cook是针对目标平台,将所引用的资源转换成对应的运行时格式。开始构建前,预设生成目标路径和中间目录,确保生成后的目录有效,给予下阶段使用。

第五阶段 Commit
提交构建结果到云空间。我们在开发阶段不管是手动还是每天自动构建,都会按照日期存放到公司内部的云空间中,方便开发人员获取和验证。

结合Gitlab实现提交时触发构建
UWA Pipeline提供了远程构建功能,激活流水线设置中的远程构建,流水线会生成一个URL地址,我们通过不同的参数配置触发流水线中对应的编译模式,达到和手动选择参数一样的效果。

通过Gitlab的Webhooks填写对应的URL地址,通常在代码仓库PR时,就可以自动触发流水线运行,从而加快构建和部署的频率,提高开发效率。

三、服务器持续部署的实现
我们使用Linux作为流水线的节点,用于内部游戏服务的自动构建和部署,实现持续集成。
游戏服务是一个组件集群,涉及到多个进程和依赖,为了提高构建速度、降低部署复杂度,通常支持一键部署。同时为了保证构建任务的互斥和步骤顺序的正确,建议大家将节点的并发构建数设为1。同时,至于针对不同测试目的,需要在同一个节点进行持续集成。这就需要通过服务隔离、运行端口分配、第三方组件和使用容器部署等方式,实现多份服务进程的部署。

可以配置节点的并发构建数,限制节点上能运行的任务数量
在单机部署测试环境中,将Linux作为流水线运行的节点时,还需要大家提前配置相关的数据库、缓存以及游戏服务所需的运行环境,我们可以通过容器方式实现快速配置。
我们的服务器部署流水线如下图所示,主要包括“Update”、“Build”和“Reboot”三个阶段。

每个阶段的具体作用为:
第一阶段 Update
从内部Gitlab拉取最新代码(C/C++、Lua)和资源配置(Lua、JSON)。通过使用流水线提供的凭证管理和Git组件,在预设的工作目录中获得最新的代码和资源。

我们在构建之前,通过Pipeline流水线设置,添加了选项参数或文本参数,设置版本目标和操作类型,方便后续在执行部署时能够根据需求进行构建。

第二阶段 Build
进入工程目录,编译Framework、依赖库和游戏代码,生成so文件和脚本文件。

第三阶段 Reboot
根据预设的目标参数,从编译工作目录中把执行程序、so文件、脚本复制到目标运行目录,停止运行过程中的游戏服务并重启。

定时构建
通过Pipeline提供的自动构建方式,设定好构建触发器,根据需求设定自动构建的频率,就可以在无人值守的情况下,实现流水线的定时自动构建。我们现阶段的服务器构建仅限用于内部测试服使用,固定是每天构建一次。

感谢钛壳树团队的精心分享,有相同需求的Unreal团队都可以参考和借鉴。如果你被这个团队CEO的能力和态度所打动,愿意加入广州钛壳树的话,现开放UE4引擎开发工程师、UE4特效设计师等岗位,小编也非常乐意为你引荐。再次感谢钛壳树团队对UWA的认可,在游戏行业工业化发展的路上我们又共同迈进了一步。
更多UWA Pipeline使用案例分享可以查看:
《乐享元游的 UWA Pipeline 最佳实践分享》
《一款ARPG游戏是如何搭建云真机系统的》
《再也不用焦虑特效造成的性能问题了》
相关文章:
你需要同款“Unreal项目自动化编译、打包和部署”方案吗?
在过往几期的UWA Pipeline最佳实践案例中,我们分享了如何通过Pipeline实现性能优化、性能管理、游戏内容验收和云真机系统的应用(实现批量真机设备的自动化测试,以及针对特效性能优化的方式),其实这些高效的方法并不局…...
电子技术——CMOS-AB类输出阶
电子技术——CMOS-AB类输出阶 本节我们研究CMOS-AB类输出阶。 经典配置 下图展示了一个经典的CMOS-AB类输出阶: 这个很像BJT二极管偏置版本的AB类输出阶,在这里二极管偏置变成了 Q1Q_1Q1 和 Q2Q_2Q2 偏置。不想BJT的情况,这里 QNQ_NQN…...
2023王道考研数据结构笔记第二章线性表
第二章 线性表 2.1 线性表的定义 2.1.1 线性表的基本概念 线性表是具有相同数据类型的n(n>0)个数据元素的有限序列,其中n为表长,当n0时线性表是一个空表。若用L命名线性表,则其一般表示为: L(a1,a2,...,ai,ai1,...,an)L(a_1…...
[chapter 11][NR Physical Layer][Layer Mapping]
前言:这里参考Curious Being系列 ,简单介绍一下NR 5G 物理层核心技术层映射.我们主要讲了一下what is layer Mapping, why need layer Mapping, how layer Mapping 参考文档:3GPP 38.211- 6.3.1.3 Layer mapping《5G NR Physical Layer | Cha…...
什么是工业物联网(IIoT)?
什么是工业物联网(IIoT)?工业物联网(IIoT) 被定义为一组设备和应用,允许大企业创建从核心到边缘的端到端连接环境。其还包括传统的物理基础设施,如集装箱和物流卡车,以收集数据,对事件做出反应,并在智能设备的帮助下做…...
「TCG 规范解读」PC 平台相关规范(4)
可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…...
CSS背景属性之颜色渐变
颜色渐变 颜色渐变其实在网页设计中并不是特别常见, 但也不可避免的会出现导航栏是渐变色这种情况或者别的不是单一颜色的情况, 例如:这样的设计解决方案并不是只可以使用颜色渐变,我们可以使用两个div拼接,将文字放…...
IPv4地址细讲
文章目录一、IPv4地址简介二、IPv4地址的表示方法点分十进制记法三、IP地址的分类四、特殊IPv4地址:全 “0” 和全 “1”五、常用的三类IP地址使用范围六、五类IP地址的范围一、IPv4地址简介 IPv4地址分5类,每一类地址都由固定长度的字段组成࿱…...
sql语句中exists用法详解
文章目录一、语法说明exists:not exists:二、常用示例说明1.查询a表在b表中存在数据2.查询a表在b表中不存在数据3.查询时间最新记录4.exists替代distinct剔除重复数据总结一、语法说明 exists: 括号内子查询sql语句返回结果不为空ÿ…...
思迅软件端口不通导致软件和软锁报错的问题
一、端口不通导致软件和软锁报错的问题 问题说明:打开软件提示到:xxx.xxx.xxx.xxx失败! 处理步骤1: 假设软锁服务器IP为192.168.0.1,分别在服务器本机和客户端电脑测试软锁服务: 在服务器的浏览器中访问地址: http:/…...
Docker之路(7.DockerFile文件编写、DockerFile 指令解释、CMD与ENTRYPOINT的区别)
1.DockerFile介绍 dockerfile 是用来构建docker镜像的文件!命令参数脚本! 构建步骤: 编写一个dockerfile文件docker build构建成为一个镜像docker run 运行镜像docker push发布镜像(DockerHub、阿里云镜像仓库) 2.Dock…...
[软件测试]如何使用Eclipse导入项目并打开
🧑🎓个人介绍:大二软件生,现学JAVA、Linux、MySQL、算法 💻博客主页:渡过晚枫渡过晚枫 👓系列专栏:[编程神域 C语言],[java/初学者],[蓝桥杯] Ὅ…...
emplace_back与push_back异同
vector的emplace_back与push_back 文章目录vector的emplace_back与push_back前言1.区别总览2.push_back支持右值引用不支持传入多个构造参数总是会进行拷贝构造3.emplace_backemplace_back可以接受多个构造参数支持原地构造前言 在vector中,通过push_back与emplace_…...
【C语言航路】第十五站:程序环境和预处理
目录 一、程序的翻译环境和执行环境 二、编译和链接 1.翻译环境 2.编译本身也分为几个阶段 3.运行环境 三、预处理 1.预定义符号 2.#define 1.#define定义标识符 2.#define定义宏 3.#define 替换规则 4.#和## 5.带副作用的宏参数 6.宏和函数的对比 7.命名约定 …...
Vue3 - 获取 Proxy 对象代理中包裹的 “真实数据“,解决对象或数组打印后是 Proxy 对象无法拿到原始数据的问题(提供 2 种详细解决方案)
前言 在 Vue3 中很多数据都被 Proxy 代理对象 “包裹”(无法拿到其真正的原始数据),另外就是请求回来的数据,例如通过 res.data.data 拿到了一个数组对象格式的数据。但是这个数据被 Proxy 包裹,你根本拿不到值无法进行处理。 本文实现了 Vue3 取到被 proxy 对象包裹的原始…...
ESP32设备驱动-ML8511紫外线传感器驱动
ML8511紫外线传感器驱动 1、ML8511介绍 ML8511 是一款紫外线传感器,适用于室内或室外获取紫外线强度。 ML8511 配备了一个内部放大器,可根据紫外线强度将光电流转换为电压。 这种独特的功能提供了与 ADC 等外部电路的简单接口。 在掉电模式下,典型的待机电流为 0.1 μ \mu…...
SC12B触摸感应芯片评测方案(1)
MM32F0160SC12B Touch Application Evaluation 文章目录MM32F0160SC12B Touch Application EvaluationIntroduction & RequirementHardwareSC12B & SC12B Sample Demo boardMini-F0160 boardSoftwareMCU Software - MM32F0160PC Tool - FreeMASTERSummaryIntroduction …...
企业如何实现精细化人员管理?五大业务场景值得关注
近年来,随着大数据、人工智能和云计算等信息技术不断升级与渗透,处在数字化变革的劳动力密集型企业希望利用更加智能化的劳动力管理软件,帮助企业实现规范化的管理。 面对企业劳动力管理理念的变化,以及数字化转型的发展渗透&…...
C/C++每日一练(20230301)
目录 1. 冒泡排序法排序 ★ 2. 有效的数独 ★★ 3. 不同的二叉搜索树 II ★★ 附录 二叉搜索树 1. 冒泡排序法排序 输入n(1≤n≤10)个整数,用冒泡排序法对其从小到大排序,共进行n-1趟,要求输出每一趟的排序情…...
Vue项目中components组件的使用笔记
目录 前言 一、components和component的区别? 二、components使用的步骤 1.创建组件vue文件 2.引入组件 3.注册组件 4.应用组件 总结 前言 本文章,只是初步了解记录components的使用步骤。 一、components和component的区别? compo…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
