Building and Hosting an Unreal Engine Dedicated Server with AWS and Docker

Luke Brady
The Startup
Published in
11 min readMar 15, 2020
Photo by Sean Do on Unsplash

Today I am going to walk you through the process of building and deploying your very own Unreal Engine 4 dedicated server running on Amazon Web Services.

What you will learn:

  • How to clone the Unreal Engine source code from GitHub
  • How to build the Unreal Engine editor from source
  • How to create an Unreal Engine project
  • How to build a dedicated server from source
  • How to package the dedicated server for Linux
  • How to build and deploy the dedicated server to AWS
  • How to connect the game client to the dedicated server running on AWS

What you will need:

The source code for this tutorial can be cloned here: https://github.com/CodeAndCoffeeBlog/building-ue4-dedicated-server-blog-1. Please clone this repository to follow along.

Building Unreal Engine

Because we are building our own dedicated server, we will first need to download the Unreal Engine 4 source code from GitHub. Epic Games’ Unreal Engine repository is private, so you will need to request access before you can clone UE4. Here is a link to do just that: https://www.unrealengine.com/en-US/ue4-on-github

What your source folder should look like after running the provided .bat files.

After UE4 has been cloned to your workstation, it is now time to setup the build dependencies and generate the project files that will allow us to open up the UE4 project in Visual Studio. To setup the dependencies, run the Setup.bat file located in the root of the Unreal Engine repository. This will download around ~100 GB of dependencies, so make sure you have plenty of free disk space available. After the setup is complete, run GenerateProjectFiles.bat. Now it is time to open up UE4 in Visual Studio.

Double click on the UE4.sln file to open up Visual Studio. We can now begin the process of compiling the Unreal Engine.

To compile the Unreal Engine from source, we will need to set UE4 as the StartUp project. Right click on UE4 -> Set as StartUp Project. This will allow us to target different build configurations provided in the UE4 solution. Click the drop down to the far left -> Development Editor. Press F5 or right click on UE4 and select Build. The build process can take a while depending on the specifications of your machine, so it may be a good time to go for a walk or play a few rounds of your favorite online Battle Royale game.

Creating A Project

After the editor build has completed, we can now start a new instance of the editor and create a demo project. To do this, press F5 to start a new instance of the Unreal Engine. For the purpose of this demo we will create a simple game called SheepsGate (taking inspiration from Dauntless here). This game will utilize the Third Person template provided by Epic.

Choose the third person template.
We will be creating a C++ project.

Select Games -> Next -> Third Person template -> Next. Select the Blueprint drop down under settings and choose C++. Change the project name to SheepsGateGame. Select Create Project. Congratulations, we now have a Third Person sample project.

After your game has been created, you will notice that Visual studio opens up instead of the Unreal Editor. This is because we chose for this to be a C++ project instead of Blueprint. Now it is time to edit our target files so that the Unreal Engine can package the client and server. You can read more about Unreal Engine target files here: https://docs.unrealengine.com/en-US/Programming/BuildTools/UnrealBuildTool/TargetFiles/index.html.

For this project, we will keep the target files very simple. Target files are located under the Source directory within our SheepsGateGame project folder. We are already provided with Game and Editor target files, but we will need to create a new file for our server. The easiest way to accomplish this is to copy the SheepsGateGame.Target.cs file to SheepsGateGameServer.Target.cs. You will need to copy this file within Windows Explorer and then open up the file in Visual Studio. Change the class and method to SheepsGateGameServerTarget. You will also need to change the Type value from TargetType.Game to TargetType.Server.

Save and close this instance of Visual Studio. Open up Windows Explorer to your project source -> right click on the SheepsGateGame.uproject file -> select Generate Visual Studio project files. This will add your new server target file to Visual Studio.

After you have generated the new project files, switch back to Visual Studio where you will be prompted to reload the editor because the files have been modified. Click Reload when prompted.

You will be prompted to reload your editor. Do it, do it!

Now we can build the dedicated server. This is very similar to when we built the development editor. To build the server, make sure SheepsGateGame is set as the startup project. If not, right click on SheepsGateGame and select Set as Startup Project. Now select the Development Server from the same drop down we used to select the editor. Right click on SheepsGateGame and select Build. This build will take a while, so you may want to take another walk or grab a coffee.

I had already built the server, so your output will include all of the build steps.

Now that the server has built successfully, change the configuration to Development editor and press F5 to open a new instance of SheepsGateGame in the Unreal Engine editor. We can go ahead and remove the ThirdPersonCharacter actor from our level. We will be utilizing the NetworkPlayerStart navigation object to spawn our character within the scene.

The NetworkPlayerStart object within the scene.

Look in the content browser under the ThirdPersonCPP folder for Maps. Move this folder to the root of the Contents directory. This will make it a little easier when we are changing the project and packaging settings. We also want to create two new levels, EntryLevel and TransitionLevel. To create new maps, right click on the Maps folder and select New Asset -> Level. We can rename the ThirdPersonTemplate map to SheepsGate.

What your Maps folder should look like.

Now we will need to change a few project settings. Click Edit -> Project Settings. Click Maps & Modes and scroll down to Default Maps.

Expand the Default Maps sections and change the Editor Startup Map and Game Default Map to EntryLevel, the Transition Map to TransitionLevel, and the Server Default Map to SheepsGate. These settings will make our client start with the empty EntryLevel map and will rely on the server to send the default map to the client. This is what we want if multiple clients are connected to the server. OK, now we just need to make a couple more changes to our packaging settings and then we will be ready to write the infrastructure code.

To change the packaging settings, click File -> Package Project -> Packaging Settings. Here we will add our maps to the packaging settings so that they will be included when we package our client and server. Expand Packaging and scroll down until you see List of maps to include in a packaged build.

Add the paths of the maps we created in the previous steps. The order of the maps does not matter.

One last thing before we package the dedicated server. We need to configure our server to listen on port 7777. To do this, we just need to create a simple blueprint in the EntryLevel map. Double click on the EntryLevel map, select Blueprints, and click Open Level Blueprint.

We will create a connection from the BeginPlay node in our blueprint. Within the blueprint editor, right click and search for Open Level. Create a connection from the Event BeginPlay node and the Open Level node and set the Level Name to the host address 0.0.0.0 and port 7777. Now press compile and exit out of the editor.

Great job! Now it is time to package the dedicated server.

Packaging The Server

Because the goal of this project is to run our dedicated server in a Linux Docker container, we will need to package our server for Linux. To do this, you will need to install the Linux cross compile dependencies I linked to at the beginning of this post. After installing the dependencies, change the build target to the server target we defined in our SheepsGateGameServer.Target.cs file. Click File -> Package Project -> Build Target -> SheepsGateGameServer.

Now we are ready to begin packaging the server. To package the server for Linux click File -> Package Project ->Linux -> Linux.

You will need to choose an output directory. I like to create a Linux directory in the project Binaries folder.

After selecting the output folder, the packaging will begin. Packaging may take a few minutes, but after it has completed it is time to start writing the infrastructure code. For these steps you will need a text editor (I will be using Visual Studio Code), Packer, Terraform, and an AWS account.

Building The Infrastructure

The infrastructure code for this project is relatively simple. First, we will create a new AMI with Packer containing our dedicated server, our Dockerfile, and the Docker service. Then we will create the Terraform code that will create a new instance of the AMI. I will also create a security group that will allow UDP 7777 into the instance. Obviously this is far from a production setup, but I think is a good way to demonstrate automating the creation and deployment process of our dedicated server as simply as possible.

For these steps, I will assume you have basic AWS knowledge including how to setup AWS credentials to access the AWS API.

We will first start with the Packer code that will create the AMI containing Docker, our dedicated server, and the Dockerfile. The first step in creating our AMI is to tar our Linux dedicated server so that we can upload it with Packer. To do this, open up MinGW (Terminal that comes with Git for Windows) and cd into the SheepsGateGame/Binaries directory where we exported the Linux server. Run the following tar command to tar and gzip the server binary:

tar -czf unreal-dedicated.tar.gz ./Linux

After the archive has been generated, copy or move it to the building-ue4-dedicated-server-blog-1/server directory. See the folder structure below.

Now it is time to build the AMI. To do this, run the following command. I have provided a variables.json file where you can include your AWS API access and secret keys.

packer.exe build -var-file=packer/variables.json packer/docker_instance.json

The Packer file will create an AMI that will install Docker, upload the Dockerfile and the Unreal Engine dedicated server archive.

After the AMI creation is completed, it is time to run the Terraform code to create an instance from the API and a security group that will allow the game client to connect to the server. I have also provided a var.tfvars file that you can use to set your AWS API access and secret keys.

cd terraform/
terraform plan -var-file=vars.tfvars -out plan
terraform apply plan

After Terraform has executed, you will get the public IP address of the instance as output. This is the IP we will use to connect our client to the server.

Copy this IP and open up Unreal Engine editor. We will now configure the EntryLevel blueprint to connect to this IP when the BeginPlay event occurs. Open the Blueprint editor and change the level IP from 0.0.0.0 to the instance’s public IP.

Compile the blueprint and exit out of the editor. Now play the game. You should see the SheepsGate level render and the player character spawn into the scene. Because we are using a server authoritative client-server model, the client will render whatever level gets sent by the server. This is why we set the default server map to our SheepsGate level and the default client map to the empty EntryLevel.

Congratulations, you have successfully connected your game client to a dedicated server running in AWS. Now it is time to package the client.

Packaging The Client

For the final step of this tutorial we will package the client. This is a relatively straight forward process, so I will try and keep this section as brief as possible.

To package the client, we first need to switch the build target from server to client. To do this select File -> Package Project -> Build Target -> SheepGateGame.

We will be packaging the client for Windows, so select File -> Package Project -> Windows -> Windows 64. Save the client package under the Binaries/Win64 folder within the SheepsGateGame source directory.

Just like the server, the client packaging process will take a few minutes. When the build has completed, you will see the following Build Successful output in the log.

After the packaging has completed, open up the project source directory and navigate to the Binaries/Win64 folder. You should see the following folder structure.

Double click on SheepsGateGame.exe to start the client process. The client will connect to the server in AWS and the SheepsGate level will render in the client.

Screen shot of client after connecting to the dedicated server.
Screen shot of client after connecting to the dedicated server.

Congratulations

You have successfully created an Unreal Engine dedicated server and built the required infrastructure to host it on AWS. As stated earlier, this is far from a production setup, but I hope that this tutorial has given you a good idea of how the client-server model in Unreal Engine works and how dedicated servers can be hosted in the cloud.

You can destroy the infrastructure in AWS with the following command.

terraform destroy -var-file=vars.tfvars

Thanks for reading!

--

--

Luke Brady
The Startup

A blog fueled by code, coffee, and a healthy dose of video games. Follow me on Twitter: @LukeBrady105