百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

适用于TeamCity的Unreal Engine支持插件,提升游戏构建效率

lipiwang 2025-03-05 17:48 22 浏览 0 评论

龙智是JetBrains授权合作伙伴、Perforce授权合作伙伴,为您提供TeamCity、Perforce Helix Core等热门的游戏开发工具及一站式服务。

TeamCity 是游戏开发的热门选择,大家选择它的原因包括支持 Perforce、可以进行本地安装,并提供了多种配置选项。除了将它主要用作通用 CI/CD 解决方案之外,JetBrains 还努力为各种构建工具提供专门支持。JetBrains 已提供 Unity 插件数年,去年也正式推出了 Unreal Engine 支持插件

在这款新插件的开发过程中,JetBrains 一直与多位游戏开发客户保持密切联系,以确保它符合从事实际 Unreal Engine 项目工作的 DevOps 团队的需求。

为 Unreal Engine 游戏设置合适的构建管道可能是一项艰巨的任务,特别是对于那些在平台独特性方面经验有限的人来说。本文,我们将带您了解基本设置,同时会展示该插件的功能,并演示分布式 BuildGraph 支持等高级功能。

新 Unreal Engine 插件生成的示例构建管道


主要功能

以下是此版插件所提供功能的快速概览:

  • 专为最常见用例(BuildCookRun、BuildGraph 和自动化测试)定制的专用运行程序。
  • 基于 BuildGraph 描述构建发行版。
  • 即时自动化测试报告。
  • 自动发现构建计算机上的 Unreal Engine 安装。
  • 兼容最新的 5.x 版 Unreal Engine,还支持 4.x 版本。


演示

在本演示中,我们将为随 Unreal 提供的两款入门级游戏 CropoutLyra 设置管道:我们将为构建代理和安装了 Unreal Engine 插件的 TeamCity Cloud 使用 AWS 基础架构(EC2 和用于 FSx for OpenZFS)。

我们将介绍两个场景:引擎已安装在代理上,以及引擎与游戏一起通过源代码构建。目前,TeamCity Cloud 不为代理提供预装的 Unreal Engine,但您可以随时添加您自己的包含所有必需 SDK 的自托管代理。我们将在这篇博文中采用这种方式。


使用 BuildCookRun 构建 Cropout

构建 Unreal 项目通常涉及多个步骤,例如:

  • 采用指定配置针对目标平台进行编译。
  • 资源烘焙(将所有资源转换为可在目标平台上读取的资源)。
  • 将项目封装为合适的分发格式。
  • 等等。

当然,之后还要进行测试!

首先,我们来看一个简单的场景,并使用标准 BuildCookRun 命令在一台计算机上按顺序运行所有阶段。

对于此场景,我们将使用撰写这篇博文时可以获取的最新普通版 Unreal Engine,并通过 EGL(Epic Games 启动器)进行安装。

将代理成功连接到 TeamCity Cloud 服务器后,我们可以在 Agents(代理)标签页中看到它。

现在,我想简单探讨一下代理的一些属性。

查看上图,我们可以看到代理发现了引擎及其版本(如您所见,我们的计算机上安装了多个引擎)。请记下此信息,因为稍后我们会将此信息用于构建步骤配置。

现在,常用的方式是将您所有的配置以代码形式存储在源代码控制系统下(也就是“配置即代码”)。在 TeamCity 中,您可以使用 Kotlin DSL 执行此操作。当然,您还可以使用传统 UI 配置,但今天我们将使用第一种方式(由于 YAML 已得到广泛使用,并且已成为事实上的标准,我们已将它添加到最近发布的 TeamCity Pipelines – 如果您还没有查看,请查看)。

用于在 TeamCity 中构建 Cropout 的 Kotlin DSL 配置如下所示:

unrealEngine {
    engineDetectionMode = automatic {
        identifier = "5.4"
    }
    command = buildCookRun {
        project = "cropout/CropoutSampleProject.uproject"
        buildConfiguration = standaloneGame {
            configurations = "Development+Shipping"
            platforms = "Mac"
        }
        cook = cookConfiguration {
            maps = "Village+MainMenu"
            cultures = "en"
            unversionedContent = true
        }
        stage = stageConfiguration {
            directory = "./staged"
        }
        archive = archiveConfiguration {
            directory = "./archived"
        }
        pak = true
        compressed = true
        prerequisites = true
    }
    additionalArguments = "-utf8output -buildmachine -unattended -noP4 -nosplash -stdout -NoCodeSign"
}

所有设置的作用都一目了然,但有几项设置需要进一步说明:

  • engine detection mode
  • 我们可以在此处指定“automatic”或“manual”。前者假定您已经在代理上安装引擎并在系统中注册。
  • 我借此机会澄清一下“注册 ”的含义:当您通过 EGL 安装 Unreal Engine 或通过源代码构建 Unreal Engine 时,此操作会写入目标计算机上的某些文件(如果使用的是 Windows,则会写入注册表)。
  • 这基本上就是自动检测模式的用途。我们读取这些文件并发布标识符作为代理属性,这样一来,您稍后便可使用这些属性为构建选择合适的代理。
  • “手动”模式允许您设置 Unreal Engine 根文件夹的准确路径,当您通过源代码构建时可能会用到该路径。稍后我们将介绍这部分内容。
  • build configuration
  • 通过调整此参数,我们可以指定所创建构建的类型,它是单机游戏、客户端、服务器,还是既是客户端又是服务器组件。
  • 根据所选的值,插件将应用 -client、-server、-noserver 标志,并相应地管理 -clientconfig、-serverconfig、-config、-targetplatform 和 -servertargetplatform 参数。

到现在为止都没问题。现在,该添加一些自动化测试并运行最终管道了。

unrealEngine {
    engineDetectionMode = automatic {
        identifier = "5.4"
    }
    command = runAutomation {
        project = "cropout/CropoutSampleProject.uproject"
        execCommand = runTests {
            tests = """
                StartsWith:JsonConfig
                Input.Triggers.Released
            """.trimIndent()
        }
        nullRHI = true
    }
    additionalArguments = "-utf8output -buildmachine -unattended -noP4 -nosplash -stdout -NoCodeSign"
}

如您所知,使用 Unreal Engine 自动化框架时,通常使用以下自动化“子命令”之一执行测试:

  • RunAll – 这是一个非常简单的命令,能够运行所有必需的测试。
  • RunFilter – 借助此命令,可以执行使用一个指定筛选器(包括 Engine、Stress、Smoke 等值)标记的测试。
  • RunTests – 这是最通用的命令,因为您可以使用该命令指定要运行的测试列表(包括使用 StartsWith 的前缀筛选器、运行组筛选器和简单的子字符串匹配)。

我们尝试在 Kotlin DSL 中保留相同的用词,以便 Unreal 用户对此感到熟悉。

还要指出的是,插件会即时解析测试结果,并以 TeamCity 自带的正确显示的格式呈现测试结果。

以下是构建结果示例:

在下方,我们可以看到发布到工件存储的游戏二进制文件。默认情况下,工件会发布到内置存储;但 TeamCity 还支持多种外部存储选项。在云环境中,可以配置发布到 S3。

UI 中的最终配置将如下所示:

下面是测试运行的步骤:

由于我们已启用 Kotlin DSL 配置并禁止在 UI 中对其进行编辑,所有设置均被禁用。


使用 BuildGraph 构建 Lyra

我们将逐步过渡到使用 Lyra 的更复杂示例。由于它是一款多人游戏,我们来构建 Linux 服务器(据我们所知,一切高性能游戏都应在 Linux 上运行!)以及 Windows 和 Linux 游戏客户端。

在前面的示例中,我们在一台计算机上按顺序运行了所有步骤。这一过程通常需要大量时间。但还有一种更好的方式,即 BuildGraph。这是一种 Unreal 方法,以声明方式(或几乎以声明方式)将构建描述为一组具有依赖关系的任务。随后,构件图的不同部分可以共同执行,或拆分到不同的计算机上。后一种方式可以显著加快整个构建过程的速度,特别适合大型复杂项目。

BuildGraph 的优点是它会自动管理作业之间的所有中间工件。您只需要共享存储。构建 Lyra 时,我们会将此共享存储用于两个目的:在单个构建中的节点之间共享数据,以及维护共享派生数据缓存 (DDC)。

我们之前提到过,我们还将通过源代码构建引擎。您通过源代码构建引擎可能是出于多种原因,但就我们的特定情况而言,我们这样做是因为无法使用任何方式通过引擎(从 EGL 安装)构建 Linux 服务器(至少在撰写这篇博文时无法实现)。这是因为此特定引擎版本未提供相应文件和 SDK。

好的,序言介绍完毕 — 我们来看看代码。

项目结构和 Perforce 中的相应流如下所示(假设您已从 Epic 的 Perforce 获取 Unreal Engine 源代码):

下面是我们将用于构建的 BuildGraph XML 脚本的节选。脚本的这一特定部分给出了编辑器的构建方式以及编译所需的工具, 其中还包含几项测试。在我们的简单示例中,这些测试采用硬编码。在真实场景中,您可能会将测试列表传递给脚本并采用更复杂的逻辑。

...

  
    
    

            ...
      

      
        
        
        
        
        
        
        
      

      ...

      
        
      
            
      
        
        
        
        
      
    
    
  

  ...

有关完整语法的描述,请参阅 Epic 网站。这里,我们本质上要做的是通过选项 EditorPlatforms 迭代传递给脚本的平台列表,并为每个平台构建编辑器。这部分代码的一个有趣的功能是代理节点的 Type 属性。

在文档中查看此表:

因此,为了在特定代理上运行一组任务,您可以修改此字段。撰写这篇博文时,为了确保一切正常运行,本部分需要对构建代理进行一些配置。也就是说,您应当在代理配置文件中定义两个属性:

  • unreal-engine.build-graph.agent.type:此属性可以是任意值(或由 ; 分隔的值列表)。相应的任务集随后将仅在至少有一个匹配项的代理上运行。
  • unreal-engine.build-graph.agent.shared-dir:前文中讨论过,为了运行分布式 BuildGraph 构建,我们需要一个共享存储位置。通过此属性,我们可以在特定代理上设置该存储位置的路径。

以下是我们的 EC2 构建代理设置:

  • 对于 Linux:
unreal-engine.build-graph.agent.type = CompileLinux;CookLinux;Linux
unreal-engine.build-graph.agent.shared-dir = /mnt/agent-shared-dir/intermediate
  • 对于 Windows(由于某些原因,将文件夹作为单独的驱动器进行装载导致一次 Windows 系统调用失败,因此我们在配置中选择了网络共享):
unreal-engine.build-graph.agent.type = CompileWin64;CookWin64;Win64
unreal-engine.build-graph.agent.shared-dir = \\\\fs-040b8d6dab476baf1.fsx.eu-west-1.amazonaws.com\\fsx\\

在真实场景中,可能需要区分执行烘焙的代理和执行编译的代理,并确保它们采用合适的规范。

我们来快速浏览一下游戏的编译、烘焙和封装过程。在我们的脚本中,我们已将构建客户端的逻辑和构建服务器的逻辑分开(因为它们传递的标志不同):


  
  
  
    
    
      
        
      
    
    
  
  
  
  
  
    
    
    
      
    
  
  
  
  
    
      
    
      
        
      
    
    
    
      
        
      
    
    
    
      
        
      
    
    
      
      
      $(PublishPlatform)Client.zip']' />
    
  
  

脚本本身不需要过多解释。我们会迭代希望客户端在其上运行的平台列表,该列表会再次作为选项传递。我们针对每个平台进行编译、烘焙资源,最后将一切封装起来。作为封装过程的最后一步,我们使用服务消息将构建的客户端作为 TeamCity 构建工件发布。

您可能已经注意到,在这部分脚本中,我们有三个代理代表构建过程的三个阶段(编译、烘焙和封装)。编译需要使用属于编辑器的工具,但不需要编辑器本身:

同时,烘焙过程需要实际的编辑器:

由于这两个过程之间没有依赖关系,它们可以在不同的计算机上并行运行(在有足够多的计算机可用的情况下)。这一简单示例演示了使用 BuildGraph 的强大功能:您只需描述共享依赖项的各项工作,然后它们就会同时运行。

为了简洁起见,我们不会显示包含服务器部分的脚本的其余部分,因为这部分内容与我们刚才描述的内容非常相似,只有标志集合不同。

最后,我们要介绍 TeamCity 中的插件配置。由于大部分工作已在 BuildGraph XML 脚本中描述,DSL 配置相当简单:

params {
    param("env.UE_SharedDataCachePath", "/mnt/agent-shared-dir/ddc")
    param("env.UE-SharedDataCachePath", "\\\\fs-040b8d6dab476baf1.fsx.eu-west-1.amazonaws.com\\fsx\\ddc")
}
steps {
    unrealEngine {
        id = "Unreal_Engine"
        name = "Build"
        engineDetectionMode = manual {
            rootDir = "engine"
        }
        command = buildGraph {
            script = "game/BuildProject.xml"
            targetNode = "BuildProject"
            options = """
                ProjectPath=%teamcity.build.checkoutDir%/game
                ProjectName=Lyra
                ClientPlatforms=Linux+Win64
                ServerPlatforms=Linux
                EditorPlatforms=Linux+Win64
                TargetConfigurations=Shipping
            """.trimIndent()
            mode = UnrealEngine.BuildGraphMode.Distributed
        }
        additionalArguments = "-utf8output -buildmachine -unattended -noP4 -nosplash -stdout -NoCodeSign"
    }
}

在这里,指定我们希望在分布式模式下运行提供的 BuildGraph 脚本。但我们可以根据自己的意愿随时选择在一台计算机上按顺序运行所有节点。我们还指定了一些环境变量,如果引擎要启用共享 DDC,则需要使用这些变量。这些文件夹应当已装载到连接至 TeamCity 的代理。

现在,您可以为我们的游戏传递以下包含三个平台选项的列表:ClientPlatforms、ServerPlatforms 和 EditorPlatforms。

UI 中的显示如下:

启动构建时,我们会获得此构建链:

因此,如我们所见,插件已将构建图转换为适当的 TeamCity 构建链。

我们可以在指定构建的相应标签页上查看已发布的工件。Linux 服务器的显示如下:

在结束之前,我们想强调一些要点,请您务必牢记:

  • 为了确保 BuildGraph 分发过程正常运行,您的构建配置应仅包含一个有效构建步骤。
  • 目前,该插件不会以任何方式管理共享存储中生成的工件的保留期。您负责正确设置保留期。
  • 这篇博文中的示例绝不可用于生产。您的真实场景可能会更加复杂。但这些示例可作为一个良好的起点。


您可以从 GitHub 仓库中获取这篇博文中展示的演示代码。如果您想尝试用于 TeamCity 的 Unreal Engine 插件,可从 JetBrains Marketplace 下载,并在 TeamCity On-Premises 服务器上安装。

对于 TeamCity Cloud 用户,我们已预装了 Unreal Engine 插件,您只需添加 Unreal Engine 构建步骤便可使用此插件。需要提醒您的是,TeamCity Cloud 代理没有预装 Unreal Engine,因此您需要使用自托管代理运行 Unreal Engine 构建。

针对一直使用预览版插件(从 0.x.x 开始的任何版本)的用户的重要说明:请注意,由于我们在 1.0.0 版中进行了更改并重新设计了多个功能,您的现有配置将被破坏。您可能需要使用新版插件重新创建这些配置。


后续计划

首先,我们期待收到您的反馈。您可以随时联系我们:通过我们的问题跟踪器提交工单或对这篇博文发表评论。

我们对今后的工作还有一些想法,包括:

  • 提供更加深入的构建日志分析。
  • 包含与 UnrealGameSync (UGS) 的集成,添加构建状态发布等功能,以及提供开箱即用的元数据服务器。
  • 添加对构建计算机上可用 SDK 的检测,可能会使用整体解决方案。
  • 了解 Gauntlet 自动化框架以及我们可以在其中执行的操作。
  • 了解我们如何利用 Epic Games 推出的构建过程中的最新进展,即查看 Unreal Build Accelerator (UBA) 并通过 TeamCity 在代理上进行协调。
  • 将插件开源。我们相信这将提高透明度,并从整体上创建更好的插件。此外,开源会带来很多乐趣。


关于 TeamCity

TeamCity 是一款强大的持续集成和部署服务器,面向以 DevOps 为中心的团队提供开箱即用的测试智能、构建问题的实时报告以及无与伦比的可扩展性。安装和部署 TeamCity,几分钟之内即可开始构建您的 DevOps 管道。TeamCity 提供本地部署和基于云的版本。

相关推荐

如何在 Linux 中压缩文件和目录?(linux压缩文件夹到指定目录)

在Linux系统中,文件和目录的压缩是一项常见且重要的操作。无论是为了节省存储空间、便于文件传输,还是进行备份管理,掌握压缩技术都能极大地提升工作效率。Linux中常用的压缩工具1.tar:打...

什么是LIM模具?与普通硅胶模具有何本质区别?

要深入理解LIM模具及其与普通硅胶模具的本质区别,需从成型逻辑、技术架构、应用价值三个层面拆解,以下是系统性解析:一、LIM模具:定义与核心技术1.定义LIM模具(LiquidInj...

前后端安全机制(前后端分离安全的token)

一、密钥安全管理方案1.动态密钥分发机制密钥与会话绑定后端为每个用户会话生成临时密钥(如AES-256密钥),通过HTTPS加密传输给前端,会话结束后自动失效。例如:javascript//...

Switch 2芯片细节曝光,英伟达专门定制支持DLSS,网友:掌机模式相当于PS4

Switch2处理器,细节被实锤!数毛社(DigitalFoundry)消息,已经确定Switch2采用的是英伟达真·定制版芯片,包含8核CPU和12GBLPDDR5X内存。GPU则基于Amp...

独立站的PageSpeed Insights 指标在seo中的作用?

这是一个非常关键的问题,关于独立站(如Shopify、WordPress、自建FastAPI/Vue等网站)的PageSpeedInsights指标(Google的网页性能评分工具)在...

前端工程化-webpack 分包的方式有哪些?

Webpack的分包(CodeSplitting)是优化应用性能的重要手段,主要通过合理拆分代码减少首次加载体积、提升缓存利用率。以下是常见的分包方式及生产/开发环境配置建议:一、Webpack...

液态硅胶(LSR)套啤注塑件的关键技术难点与解决方案?

液态硅胶(LSR)套啤注塑件(即二次注塑成型,一次成型基材+二次LSR包胶)在医疗、电子、汽车等领域应用广泛,但其关键技术难点需从材料、模具、工艺等多维度突破。以下是核心难点及解决方案:一、关...

spa首屏加载慢怎样解决(spa首屏优化)

SPA(SinglePageApplication,单页应用)首屏加载慢是一个常见问题,主要原因通常是首次加载需要拉取体积较大的JavaScript文件、样式表、初始化数据等。以下是一些常见的...

揭秘|为什么新华三(H3C)要自主研发运维管理软件?

1概述1.1产生背景随着互联网技术的快速发展,企业对计算、网络的需求也越来越大。为了保证整个数据系统可靠、稳定地运行,相关企业对运维系统的要求越来越高,运维成本也在随之逐步增加。H3C公司自主研发的运...

动态主机配置协议——DHCP详解(dhcp动态主机配置协议的功能是?)

一、DHCP简介DHCP(DynamicHostConfigurationProtocol),动态主机配置协议,是一个应用层协议。当我们将客户主机ip地址设置为动态获取方式时,DHCP服务器就会...

OGG同步到Kafka(oggforbigdata到kafka)

目的:测试使用OGG将数据单向同步到Kafka上。简要说明:Kafka使用单节点单Broker部署;单独部署简单ZooKeeper;需要使用到JAVA1.8;OGG需要2个版本,一个fororacl...

Zabbix入门操作指南(zabbix4.0使用手册)

上篇:安装与配置一.概述在开始之前,一些概念和定义需要我们提前了解一下(以下内容摘自官方网站)。1.1几个概念架构Zabbix由几个主要的功能组件组成,其职责如下所示。ServerZabbixs...

绝对干货!升级MySQL5.7到MySQL8.0的最佳实践分享

一、前言事出必有因,在这个月的某个项目中,我们面临了一项重要任务,即每年一次的等保测评整改。这次测评的重点是Mysql的一些高危漏洞,客户要求我们无论如何必须解决这些漏洞。尽管我们感到无奈,但为了满足...

pytorch v2.7.0震撼发布!Blackwell GPU支持+编译性能狂飙,AI开发

重点内容测试版(Beta):oTorch.Compile支持Torch函数模式oMega缓存原型(Prototype):o支持NVIDIABlackwell架构oPyTorch...

kubernetes1.31.3集群搭建(上)(kubectl连接集群)

1集群规划1.1物理机环境电脑操作系统CPU内存硬盘网卡IP地址(静态)虚拟机软件服务器操作系统联想Windows11Intel12900K24核128GB4TBPcIE4.0无线网卡192...

取消回复欢迎 发表评论: