UE4基础:一键出包脚本

UE4 提供了一个非常好用的脚本 BuildGraph ,使用 xml 语法,用来配置控制 UnrealBuildTool,AutomationTool 来自定义出包流程,具体用法见官方文档

本文的目的就是使用 BuildGraph,在工作 PC 机上可以出各个平台的包和 DedicatedServer,如有需要可自己在这个基础上进行扩展(BaseCommand.bat 里有几个路径需要根据自己的项目进行修改),一般出包相关的脚本都统一放到工程目录的 Build 文件夹下方便提交到库里进行版本控制,如图

BuildFolder.png

AutomationScript

在 Build 目录下新建一个文件 AllBuild.xml,内容如下

<?xml version='1.0' ?>
<BuildGraph xmlns="http://www.epicgames.com/BuildGraph" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epicgames.com/BuildGraph ../../Engine/Build/Graph/Schema.xsd">

    <!-- Option Begins -->
    <Option Name="BuildEditor" DefaultValue="true" Description="Build editor or not. Default is build."/>
    <Option Name="BuildTools" DefaultValue="false" Description="Build tools or not. Default is not build."/>
    <Option Name="BuildConfiguration" DefaultValue="Development" Description="Debug, Development or Shipping."/>
    <Option Name="WithClean" DefaultValue="false" Description="Clean before build."/>
    <Option Name="WithDebugInfo" DefaultValue="false" Description="Enable debug info in Development and Shipping."/>
    <Option Name="WithCook" DefaultValue="true" Description="Cook asset."/>
    <Option Name="IgnoreCookErrors" DefaultValue="false" Description=""/>
    <Option Name="IterativeCooking" DefaultValue="false" Description=""/>
    <Option Name="ProjectDir" DefaultValue="" Description=""/>
    <Option Name="ProjectName" DefaultValue="" Description=""/>
    <!-- Option Ends -->

    <!-- Command Begins -->
    <Property Name="CleanCommand" Value="" />
    <Property Name="CleanCommand" Value="-Clean" If="$(WithClean)"/>

    <Property Name="BuildCommand" Value="-Build -NoCompileEditor -SkipBuildEditor"/>
    <Property Name="BuildCommand" Value="$(BuildCommand) -ForceDebugInfo" If="$(WithDebugInfo)"/>

    <Property Name="PakCommand" Value="-Pak"/>

    <Property Name="CookCommand" Value="-Cook -SkipCookingEditorContent -UnversionedCookedContent -CookPartialgc -Compressed"/>
    <Property Name="CookCommand" Value="$(CookCommand) -IgnoreCookErrors" If="$(IgnoreCookErrors)"/>
    <Property Name="CookCommand" Value="$(CookCommand) -IterativeCooking" If="$(IterativeCooking)"/>
    <Property Name="CookCommand" Value="-SkipCook" If="'$(WithCook)' == false"/>

    <Property Name="StageCommand" Value="-Stage"/>

    <Property Name="PackageCommand" Value="-Package"/>

    <Property Name="ArchiveCommand" Value="-Archive -ArchiveDirectory=$(ProjectDir)\Binaries"/>

    <Property Name="BaseCommand" Value="-project=$(ProjectDir)\$(ProjectName).uproject -UTF8Output -NoP4 -Prereqs $(CleanCommand) $(BuildCommand) $(PakCommand) $(CookCommand) $(StageCommand) $(ArchiveCommand)"/>
    <Property Name="BaseGameCommand" Value="$(BaseCommand) -ClientConfig=$(BuildConfiguration) $(PackageCommand)"/>
    <Property Name="BaseServerCommand" Value="$(BaseCommand) -DedicatedServer"/>

    <!-- Command Ends -->

    <Agent Name="Tools Win64" Type="BuildOnWindows">
        <Node Name="Build Tools Win64" If="$(BuildTools)">
            <Compile Target="ShaderCompileWorker" Configuration="Development" Platform="Win64" Tag="#Build Tools Win64"/>
            <Compile Target="UnrealPak" Configuration="Development" Platform="Win64" Tag="#Build Tools Win64"/>
        </Node>
    </Agent>

    <Agent Name="Editor Win64" Type="BuildOnWindows">
        <Node Name="Build UnrealHeaderTool Win64">
            <Compile Target="UnrealHeaderTool" Platform="Win64" Configuration="Development"/>
        </Node>
        <Node Name="Build Editor Win64" Requires="Build UnrealHeaderTool Win64" If="$(BuildEditor)">
            <Compile Target="$(ProjectName)Editor" Platform="Win64" Configuration="Development" Arguments="$(ProjectDir)\$(ProjectName).uproject" Tag="#Build Editor Win64"/>
        </Node>
    </Agent>

    <!-- Games Begins -->

    <Agent Name="Game Win64" Type="BuildOnWindows">
        <Node Name="Build Game Win64">
            <Property Name="Win64GameCommand" Value="-TargetPlatform=Win64 $(BaseGameCommand)"/>
            <Log Message="BuildCookRun with arguments: $(Win64GameCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(Win64GameCommand)"/>
        </Node>
    </Agent>

    <Agent Name="Game Linux" Type="BuildOnWindows">
        <Node Name="Build Game Linux">
            <Property Name="LinuxGameCommand" Value="-TargetPlatform=Linux $(BaseGameCommand)"/>
            <Log Message="BuildCookRun with arguments: $(LinuxGameCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(LinuxGameCommand)"/>
        </Node>
    </Agent>

    <Agent Name="Game Mac" Type="BuildOnWindows">
        <Node Name="Build Game Mac">
            <Property Name="MacGameCommand" Value="-TargetPlatform=Mac $(BaseGameCommand)"/>
            <Log Message="BuildCookRun with arguments: $(MacGameCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(MacGameCommand)"/>
        </Node>
    </Agent>

    <Agent Name="Game Android" Type="BuildOnWindows">
        <Node Name="Build Game Android">
            <Property Name="AndroidGameCommand" Value="-TargetPlatform=Android -CookFlavor=ETC2 $(BaseGameCommand)"/>
            <Log Message="BuildCookRun with arguments: $(AndroidGameCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(AndroidGameCommand)"/>
        </Node>
    </Agent>

    <Agent Name="Game iOS" Type="BuildOnWindows">
        <Node Name="Build Game iOS">
            <Property Name="iOSGameCommand" Value="-TargetPlatform=IOS $(BaseGameCommand)"/>
            <Log Message="BuildCookRun with arguments: $(iOSGameCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(iOSGameCommand)"/>
        </Node>
    </Agent>

    <!-- Games Ends -->

    <!-- Servers Begins -->

    <Agent Name="Server Win64" Type="BuildOnWindows">
        <Node Name="Build Server Win64">
            <Property Name="Win64ServerCommand" Value="-ServerTargetPlatform=Win64 $(BaseServerCommand)"/>
            <Log Message="BuildCookRun with arguments: $(Win64ServerCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(Win64ServerCommand)"/>
        </Node>
    </Agent>

    <Agent Name="Server Linux" Type="BuildOnWindows">
        <Node Name="Build Server Linux">
            <Property Name="LinuxServerCommand" Value="-ServerTargetPlatform=Linux $(BaseServerCommand)"/>
            <Log Message="BuildCookRun with arguments: $(LinuxServerCommand)"/>
            <Command Name="BuildCookRun" Arguments="$(LinuxServerCommand)"/>
        </Node>
    </Agent>

    <!-- Servers Ends -->
</BuildGraph>

再新建一个 BaseCommand.bat 用来调用 AutomationScript,内容如下

@echo off

set CurrentPath=%~dp0

rem 以下参数根据自己实际路径进行修改

set ProjectName=FPSDemo
set ProjectDir=%CurrentPath%..
set UATPath="%CurrentPath%..\..\Engine\Build\BatchFiles\RunUAT.bat"
set AutomationScriptPath="%CurrentPath%AllBuild.xml"

rem ends

if %Target%=="" set Target="Build Editor Win64"
if "%IterativeCooking%"=="" set IterativeCooking=true
if "%BuildConfiguration%"=="" set BuildConfiguration=Development
if "%WithClean%"=="" set WithClean=false

call %UATPath% BuildGraph -Script=%AutomationScriptPath% -Target=%Target% -set:ProjectDir=%ProjectDir% -set:ProjectName=%ProjectName% -set:IterativeCooking=%IterativeCooking% -set:BuildConfiguration=%BuildConfiguration% -set:WithClean=%WithClean%

pause

Windows 相关的包

编辑器

Build 目需下新建 Build_Editor_Win64.bat,双击运行编译编辑器相关dll,内容如下

@echo off

set Target="Build Editor Win64"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

WindowsEditor.png

Game

Build 目需下新建 Build_Game_Win64.bat,双击运行打包 Win64 客户端,内容如下

@echo off

set Target="Build Game Win64"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

WindowsNoEditor.png

Dedicated Server

Build 目需下新建 Build_Server_Win64.bat,双击运行打包 Win64 服务端,内容如下

@echo off

set Target="Build Server Win64"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

注意,出 DS 包之前确保 Source 目录下有 Server Target 的定义文件,如图

ServerTarget.png

出包结果如图

WindowsServer.png

Linux 相关的包

想要在 Windows 出 Linux 平台的包,需要先安装交叉编译环境,并且执行引擎 Setup.bat 时,需要额外的命令行参数 -include=Linux 下载 Linux 平台的依赖库

交叉编译环境

安装文档见官网 Cross-Compiling for Linux

安装好后最好重启下电脑

Game

Build 目需下新建 Build_Game_Linux.bat,双击运行打包 Linux 客户端,内容如下

@echo off

set Target="Build Game Linux"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

LinuxNoEditor.png

Dedicated Server

Build 目需下新建 Build_Server_Linux.bat,双击运行打包 Linux 服务端,内容如下

@echo off

set Target="Build Server Linux"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

LinuxServer.png

Android 包

执行引擎 Setup.bat 时,需要额外的命令行参数 -include=Android 下载 Android 平台的依赖库

安装 Android 编译环境

打开 [Path To Your UE4 Root]\Engine\Extras\AndroidWorks\Win64 路径,运行 CodeWorksforAndroid.exe,使用默认选项即可,下载安装 Android sdk, ndk, java jdk,如图

CodeWorksforAndroid.png

编辑器 Android 配置

打开项目编辑器,打开项目配置,选择 Android 菜单,点击配置按钮,然后再点击接受按钮完成配置,如图

AndroidConfig.png

正确安装好 Android 编译环境后,编辑器会根据系统环境变量识别各个 SDK 的路径,如图

AndroidSDK.png

Game

Build 目需下新建 Build_Game_Android.bat,双击运行打包 Android 客户端,内容如下

@echo off

set Target="Build Game Android"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

AndroidETC2.png

Mac/iOS 相关的包

要在 Windows 上出 Mac 和 iOS 包,需要走远程编译流程,首先要有一台 Mac,在 Windows 上通过 ssh 连接到 Mac 上,将代码文件上传到 Mac 上进行编译,最后将编译完成后的程序下载回来,然后在本机进行资源 Cook,最终打包到一起

同样,执行引擎 Setup.bat 时,需要额外的命令行参数 -include=Mac -include=IOS 下载 Mac/IOS 平台的依赖库

Mac 设置

  • 打开远程登录: 系统偏好设置 -> 共享 -> 勾选远程登录,在右边可以看到相应的用户名和ip信息
  • 节能设置: 系统偏好设置 -> 节能 -> 勾选 当显示器关闭时,防止电脑自动进入睡眠。不然的话显示器关闭时,ssh就可能连不上了
  • 检查xcode版本: 引擎版本和 xcode 版本有一定的对应关系,比如 4.18 要用 xcode 9.2 及之前的版本编译,一般最新引擎版本用最新的 xcode 去编总是没错
  • 修改ssh设置: 这一步不是必须的,在 /etc/ssh 目录下有个 sshd_config 的配置文件,里面有几项配置可以看着改下(比如公用的 Mac 就可以将连接数增大一点),如果修改需要将前面的注释符 # 号去掉
    • ClientAliveInternal 客户端超时时间,单位秒
    • ClientAliveCountMax 客户端超时次数,当一个连接连续超时对应次数时,就断开
    • MaxStartups x:y:z 从第x个连接开始,以y的概率拒绝连接,直到z个为止
  • 安装苹果开发者证书

PC 设置

  • 打开项目编辑器,在项目设置中 Platforms -> iOS 菜单下,导入描述文件和 p12 证书,Status 里显示 Valid 就说明证书匹配,如图

    import.png

    import_result.png

  • 下拉滚动条,在 Build 菜单中设置远程 Mac 主机信息(ip地址端口,登录用户名),然后点击 Generate SSH Key 按钮,如图

    GenerateSSHKey.png

  • 在跳出来的命令行窗口中,先按任意键继续,第一次会出现如下提示,输入 yes

    step1.png

  • 再输入 Mac 电脑的登录密码(密码是不会回显的),如图

    step2.png

  • 然后会提示 Enter passphrase,直接回车,如图

    step3.png

  • 之后会出现如图提示,再按任意键继续

    step4.png

  • 再次输入 Mac 的登录密码

    step5.png

  • 最后如图没有看到错误提示的话,就是成功了,如图,按任意键结束

    step6.png

  • C:\Users[YourUserName]\AppData\Roaming\Unreal Engine\UnrealBuildTool\SSHKeys[MacIp][MacUserName] 目录下就会看到生成的密钥了

Mac Game

Build 目需下新建 Build_Game_Mac.bat,双击运行打包 Mac 客户端,内容如下

@echo off

set Target="Build Game Mac"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

MacNoEditor.png

iOS Game

目前用 BuildGraph 远程出 iOS 包有一个 BUG,见 UE-64059 ,这个 BUG 官方会在 4.22 中修复,4.22 版本之前可以自己手动修改,打开 Engine\Source\Programs\AutomationTool\IOS\IOSPlatform.Automation.cs,在 PreBuildAgenda 函数中,将 Agenda.DotNetProjects.Add(@"Engine\Source\Programs\IOS\iPhonePackager\iPhonePackager.csproj"); 这行代码注释掉

Build 目需下新建 Build_Game_iOS.bat,双击运行打包 iOS 客户端,内容如下

@echo off

set Target="Build Game iOS"
set IterativeCooking=true
set BuildConfiguration=Development
set WithClean=false

call BaseCommand.bat

出包结果如图

IOS.png