{"id":1789,"date":"2017-02-11T17:34:27","date_gmt":"2017-02-11T16:34:27","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=1789"},"modified":"2023-06-09T14:20:35","modified_gmt":"2023-06-09T12:20:35","slug":"uat-automation","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/02\/11\/uat-automation\/","title":{"rendered":"Automate deployment with the Unreal Engine using the Unreal Automation Tool (UAT)"},"content":{"rendered":"<p>The Unreal Engine 4 from Epic Games is a powerful tool to create any type of game or even application, however the implemented\u00a0automation and build system is barely documented, if at all. This post will show the necessary steps to\u00a0build, cook and package a game using the Unreal Automation Tool (UAT) \u00a0and gives a brief overview over the somewhat hidden tools.<\/p>\n<p><!--more--><\/p>\n<h2>Terminology and Engine Types<\/h2>\n<p>Before we can start to delve into the\u00a0automation system we need to define some terminology. The central tool we are going to use is the <em>Unreal Automation Tool (UAT)<\/em>. This tool is the primary entry point for any sort of automation inside the engine aside from building and packaging an application. The UAT provides <em>commandlets<\/em>, which are usually a set of commands to be run inside the engine&#8217;s ecosystem. The UAT is started using the appropriate script for the underlying operating system (*.sh for linux, *.command for mac and *.bat for Windows), which are located in <em>Engine\/Build\/BatchFiles<\/em>. For UAT this would be the <em>RunUAT<\/em> script. Appending <em>-list\u00a0<\/em>returns a list of available commands. More information for UAT can be retrieved using the <em>-help<\/em>\u00a0switch.<em>\u00a0<\/em>The same applies for each commandlet, just write <em>RunUAT &lt;Commandlet&gt; -help<\/em>. To get more information and possible switches for this command.<\/p>\n<p>It is important to know on which type of engine the UAT is run. There are three different engine types and they require some changes to the command line depending which is used.<br \/>\nThe first and most common engine type for smaller projects is the so called\u00a0<em>Rocket<\/em> build. The rocket build is what you get, when you install the engine via the Epic Games Launcher. This is a pre-built, ready-to-use version of the engine. Depending on the choices you select in the launcher, it contains all necessary dependencies to package a project for all desktop applications and mobile targets.<\/p>\n<p>The next type of engine is the\u00a0<em>source build<\/em>. This build type is what you get when you clone or download the Unreal Engine repository from GitHub (if you have linked your GitHub account to your Epic Games profile).<br \/>\nThis is the most versatile type of engine as the source of the engine can be changed and recompiled. Licensees for console development also get access to extra source code to be compiled in for console support. While this engine type is the most versatile it comes with the cost that everything needs to be compiled, an editor build usually takes from 15-60 minutes, depending on the system used and\u00a0takes up\u00a0more than 4\u00a0times the size of\u00a0pre-built engines.<\/p>\n<p>To\u00a0speed up development for your team one can create an\u00a0<em>installed build\u00a0<\/em>from a source engine.\u00a0The supported platforms can be chosen upon creating this build. This type is supported starting with 4.13 and can be easily created, see <a href=\"https:\/\/docs.unrealengine.com\/latest\/INT\/Programming\/Development\/InstalledBuildReference\/\">this link for more information<\/a>. This build is very similar to the rocket build, however it can contain own changes and additional target platforms.<\/p>\n<p>One last tool we need for automatic deployment is the <em>Unreal Build Tool (UBT)<\/em>, which, hence the name, is the main tool for building source code inside the engine.\u00a0It looks like the UAT is currently meant to be run from inside the editor. When trying to package a project just using the UAT it will\u00a0fail (on a clean version of the project) because of missing editor dlls of the project.\u00a0To create the missing dlls we need to use the UBT to build the editor target for our project and we are good to go.<\/p>\n<h2>Step 1: Building the Editor Target<\/h2>\n<p>Before we can launch the UAT we first need to compile the editor targets for our project to get up-to date versions of our editor dlls. To build those dlls we run the UBT for our project editor target for our operating system (e.g. Win64) in the development configuration:<\/p>\n<p><code class=\"\" data-line=\"\">Build\/BatchFiles\/Build.bat &lt;ProjectName&gt;Editor Win64 Development &lt;PathToProjectFile&gt;.uproject -WaitMutex<\/code><\/p>\n<p>For a clean build either the <em>Clean<\/em> script can be run before or instead of the build script the <em>Rebuild\u00a0<\/em>script can be used. The\u00a0<em>-WaitMutex\u00a0<\/em>switch tells the build tool to wait for the global mutex for this UBT instance. Omitting this switch lets the UBT return with an error if it is currently used elsewhere.<\/p>\n<h2>Step 2: BuildCookRun<\/h2>\n<p>The\u00a0complete packaging\u00a0process is available using the\u00a0<em>BuildCookRun<\/em> commandlet inside the UAT. As the name of the commandlet suggests this is a three part process.<\/p>\n<ul>\n<li>Build: Compile the\u00a0engine, engine plugins, project plugins and the project itself with all necessary runtime modules which usually creates a single executable file at the end<\/li>\n<li>Cook: Convert all\u00a0referenced assets to the respective runtime formats for the target platform (e.g. on Windows convert textures to DDS format), compile still missing shaders, compile Blueprints to their binary representation and strip out any editing information.<\/li>\n<li>Run: The last step can have a multitude of actions to be performed. In the scope of build automation we usually want to package our assets into pak files and archive the complete project into a folder for further processing (e.g. uploading to Steam). Other features include automatic deployment to connected devices via network or for mobile connected via USB and start the game on the device. These are usually not part in a fully automated process and will not be described here\u00a0much further.<\/li>\n<\/ul>\n<p>A complete command line for this process could look like this:<\/p>\n<p><code class=\"\" data-line=\"\">call Engine\\Build\\BatchFiles\\RunUAT.bat&quot; BuildCookRun -Project=&quot;&lt;ProjectPath&gt;.uproject&quot; -NoP4 -NoCompileEditor -Distribution -TargetPlatform=Win64 -Platform=Win64 -ClientConfig=Shipping -ServerConfig=Shipping -Cook -Map=List+Of+Maps+To+Include -Build -Stage -Pak -Archive -ArchiveDirectory=&lt;ArchivePath&gt; -Rocket -Prereqs -Package<\/code><\/p>\n<p>Let&#8217;s go through this one by one:<\/p>\n<ul>\n<li>BuildCookRun: We want to to use the BuildCookRun commandlet<\/li>\n<li>-Project=&#8221;&lt;ProjectPath&gt;\/&lt;ProjectName&gt;.uproject&#8221;: <em>Required<\/em> parameter, <strong>absolute\u00a0<\/strong>path to your uproject file<\/li>\n<li>-NoP4: We do not want to interact with Perforce during this build (opposite would be: -P4)<\/li>\n<li>-NoCompileEditor: As far as I know this seems to be broken, omitting this flag should build the editor parts we previously built using the UBT, however at least for me this does not work.<\/li>\n<li>-Distribution: Mark this build for distribution (especially for mobile platforms creates a distribution package, this usually means using distribution certificates)<\/li>\n<li>-TargetPlatform=&lt;Platform1&gt;+&lt;Platform2&gt;: For which platforms we want to package (separated with a +)<\/li>\n<li>-ClientConfig=Shipping: Which configuration we want to package, options are Debug, Development, Test and Shipping<\/li>\n<li>-ServerConfig=Shipping: Target platform for the server to be build against<\/li>\n<li>-Cook: We want to run the cook step<\/li>\n<li>-Map=List+Of+Maps+To+Include: Specific list of map names, separated using a +, to include. If omitted it will use the ones specified in the project settings<\/li>\n<li>-Build: We want to run the build step<\/li>\n<li>-Stage: Save the cook result in a staging directory<\/li>\n<li>-Pak: Use pak files instead of plain file system directories<\/li>\n<li>-Archive: We want to get a archive the complete output in a directory<\/li>\n<li>-ArchiveDirectory=&lt;ArchivePath&gt;: The path to archive the project<\/li>\n<li>-Rocket: We are using an installed\/Rocket build<\/li>\n<li>-Prereqs: Include Unreal Engine Prerequisites installer<\/li>\n<li>-Package: Create a package for the target platform (e.g. an app file on Mac, apk on Android or ipa on iPhone)<\/li>\n<\/ul>\n<p>Note that\u00a0all switches are case insensitive (except for paths on case-sensitive platforms of course).<\/p>\n<p>The above collection of switches and parameters are a solid basis for packaging a ready-to-run application and fully suffice. The next list\u00a0shows a couple more useful switches to consider:<\/p>\n<ul>\n<li>-Compile: This switch is usually required on source builds. It tells the UAT to compile itself before running any commandlets, however on Installed\/Rocket builds this will result in an error as the sources for UAT are not\u00a0part of those engine distributions.<\/li>\n<li>-UnversionedCookedContent: Omit versions in\u00a0assets, all loaded assets are assumed to be the current version.<\/li>\n<li>-EncryptIniFiles: Encrypt your ini files, which makes it hard to tamper with them<\/li>\n<li>-CreateReleaseVersion=&lt;VersionName&gt;: Creates information about this version inside you project folder under Releases, this information can be used for patches and dlc<\/li>\n<li>-BasedOnReleaseVersion=&lt;VersionName&gt;: This build is based on the given version, used for patches and dlc, to only include new or modified files.<\/li>\n<li>-Compressed: Compress the pak files for smaller disk usage (and increased loading times)<\/li>\n<li>-Iterate: Only cook not already cooked items (if running on the same directory as a build before), if omitted it will cook all content<\/li>\n<li>-CookAll: Cook all content, not only referenced assets<\/li>\n<li>-CookOnTheFly: Does not cook the content, but starts the cook process in servermode, where a game can connect to using the -FileHostIP=&lt;IP&gt; parameter to connect to this server. The server will then cook requested content on the fly.<\/li>\n<li>-Run: Start the project after deployment<\/li>\n<li>-Device=&lt;DeviceName1&gt;+&lt;DeviceName2&gt;: Device name to run the game on (separated with +)<\/li>\n<li>-NullRhi: Run the game without any render hardware interface (e.g. for running unit tests on headless devices)<\/li>\n<li>-NativizeAssets: Supported since 4.13, allows C++\u00a0code generation from Blueprint scripts<\/li>\n<\/ul>\n<h2>Step 3: Profit!<\/h2>\n<p>With all this information it should be easy to successfully\u00a0integrate the engine deployment into your automation process.<\/p>\n<p>If you happen to use buildbot as your CI\/CD framework you may want to take a look at <a href=\"https:\/\/pypi.python.org\/pypi\/buildbot-UnrealEngine\">my plugin<\/a> to simplify interfacing with the UAT from buildbot.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Documentation and Getting started guide for the Unreal Automation Tool (UAT) and Unreal Build Tool (UBT) included in the Unreal Engine 4.<\/p>\n","protected":false},"author":191,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[659,650,651,2],"tags":[73,72,74,71],"ppma_author":[714],"class_list":["post-1789","post","type-post","status-publish","format-standard","hentry","category-devops","category-scalable-systems","category-system-designs","category-system-engineering","tag-automation","tag-deployment","tag-games","tag-unreal-engine"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1711,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/11\/26\/snakes-exploring-pipelines-a-system-engineering-and-management-project\/","url_meta":{"origin":1789,"position":0},"title":"Snakes exploring Pipelines &#8211; A \u201cSystem Engineering and Management\u201d Project","author":"Yann Loic Philippczyk","date":"26. November 2016","format":false,"excerpt":"Part 0: Introduction This series of blog entries describes a student project focused on developing an application by using methods like pair programming, test driven development and deployment pipelines. Once upon a time, which was about one and a half months ago, an illustrious group of three students found together,\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"A python. (Because snakes. Not the language.) Source: https:\/\/rashmanly.files.wordpress.com\/2008\/10\/1439659.jpg","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/11\/0_1-300x300.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1758,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/01\/12\/snakes-exploring-pipelines-a-system-engineering-and-management-project-5\/","url_meta":{"origin":1789,"position":1},"title":"Snakes exploring Pipelines &#8211; A \u201cSystem Engineering and Management\u201d Project","author":"Yann Loic Philippczyk","date":"12. January 2017","format":false,"excerpt":"Part 4: Jenkins and Wrap Up This series of blog entries describes a student project focused on developing an application by using methods like pair programming, test driven development and deployment pipelines. Our first blog entry for this year will at the same time be the final one for this\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/01\/jenkins_code-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/01\/jenkins_code-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/01\/jenkins_code-1.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":5175,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/benefiting-kubernetes-part-2-deploy-with-kubectl\/","url_meta":{"origin":1789,"position":2},"title":"Migrating to Kubernetes Part 2 &#8211; Deploy with kubectl","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Migrating from Bare Metal to Kubernetes The interest in software containers is a relatively new trend in the developers world. Classic VMs have not lost their right to exist within a world full of monoliths yet, but the trend is clearly towards\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":5163,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-1-introduction\/","url_meta":{"origin":1789,"position":3},"title":"Migrating to Kubernetes Part 1 &#8211; Introduction","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Introduction The great challenge of collaborative working in a software developer team is to enable a high level of developer activity while ensuring a high product quality. In order to achieve this often CI\/CD processes are utilized. Talking about modern development techniques\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":382,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/02\/21\/wrap-up-seeing-the-bigger-picture-part-5\/","url_meta":{"origin":1789,"position":4},"title":"Jenkbird &#8211; Wrap up &#038; seeing the bigger picture &#8211; Part 5","author":"J\u00f6rg Einfeldt","date":"21. February 2016","format":false,"excerpt":"Kchhhhhh, Kchhhhhh, Kchhhhhhh... - Ernie on companies without CI Hello internet and welcome to the last part of our\u00a0tutorial series about\u00a0Continuous Integration, Code Deployment and Automated Testing with Jenkins. If you arrived at this post and have read all the others we are very proud of you, hope you enjoyed\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"bert","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/02\/bert-186x300.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":26830,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/02\/24\/gitops-demystified-principles-practices-and-challenges\/","url_meta":{"origin":1789,"position":5},"title":"GitOps Demystified: Principles, Practices, and Challenges","author":"Kay Kn\u00f6pfle","date":"24. February 2025","format":false,"excerpt":"GitOps, a term coined by Alexis Richardson (CEO of Weaveworks) in 2017, represents a modern approach to continuous deployment and infrastructure management that leverages Git as its core technological foundation [1]. At its essence, GitOps extends the familiar Git workflow patterns from application development to infrastructure management, establishing Git repositories\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/whats_gitops.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/whats_gitops.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/whats_gitops.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/whats_gitops.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":714,"user_id":191,"is_guest":0,"slug":"mp120","display_name":"Marvin Pohl","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/55ccc3c524d78fe351702d023b7b87c8cd24a77bae89fc480b361aa237495088?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/1789","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/191"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=1789"}],"version-history":[{"count":18,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/1789\/revisions"}],"predecessor-version":[{"id":2258,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/1789\/revisions\/2258"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=1789"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=1789"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=1789"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=1789"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}