In this article series, we will implement a multiplayer web game. You will get insights on how to use CI/CD workflows for game development and how they support the development process. We will deploy both our game client and server in an automated way to Azure. For developing, building, deploying, and hosting our game, we will use only free tools and services. You will learn through a minimalistic example how to realize a multiplayer web game. Let’s get started.
Setting Up Your CI/CD and Build a WebGL Game
We’ll use a CI/CD pipeline to create a Unity WebGL game in the first part of this article series.
What is CI/CD and why do we need that?
Continuous Integration (CI) has been around for a decade and has evolved into one of the top best practices in modern software development. When multiple developers work on the same source code, developing their branches, merging all their codes can be a tedious task as the code diverted far away from each other. Here is where CI can help. It allows developers to integrate their code frequently, and verify the changes by executing automated build and testing tasks.
CD (Continous Deployment) starts where CI finishes. CD allows frequent deployment into different environments, such as development or production, it even allows deployment into different platforms.
CI/CD makes it possible to deliver code changes more frequently and accurately and this allows users to use and react faster to the changes, instead of waiting for a big release.
There are a lot of tools available for the implementation CI/CD, for example, Jenkins, Atlassian Bamboo, Travis CI, or GitHub Actions. Though the way of pipeline definitions are a bit different, but these tools have similar features. In this article, we will use GitHub Actions. GitHub Actions is preferred because we can upload our workflow description to the same tool where we store the source code.
Creating A Game in Unity
In Unity, we will implement a very minimalistic Ball-On-A-Table game. This is a multiplayer game where you can move the ball with the arrows. Check my earlier post to have a better understanding of how Mirror works.
For now, carry out these steps:
- Import Mirror Networking.
- Create a NetworkManager game object, with a NetworkManager component. Don’t forget to add the Player Prefab to it.
- Change the default Transform to Simple Web Transport, because we will build a WebGL game.
- Add NetworkIdentity and NetworkTransform components to the Player Prefab (the sphere).
- Implement a Controller.cs and add to the Player Prefab:
using UnityEngine;
using Mirror;
public class Controller : NetworkBehaviour
{
private float speed = 0.05f;
void Update()
{
if (isLocalPlayer)
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal") * speed, 0, Input.GetAxis("Vertical") * speed);
transform.position = transform.position + movement;
}
}
}
You can also create a simple GUI to let the player start and exit the game session:
using UnityEngine;
using Mirror;
public class GUI : MonoBehaviour
{
bool isGameStarted = false;
NetworkManager networkManager;
void Start()
{
networkManager = GetComponent<NetworkManager>();
}
void OnGUI()
{
GUILayout.Window(0, new Rect(0, 0, 300, 0), GamePanel, "Multiplayer Game");
}
void GamePanel(int windowID)
{
if (!isGameStarted)
{
if (GUILayout.Button("Start!"))
{
networkManager.StartClient();
isGameStarted = true;
}
} else if (isGameStarted)
{
if (GUILayout.Button("Cancel"))
{
networkManager.StopClient();
isGameStarted = false;
}
}
}
}
Code language: HTML, XML (xml)
Setting Up GitHub and Upload Your Code
GitHub is a Git repository hosting service. With its GitHub Actions feature, you can also implement a CI/CD pipeline, which is very practical, as you have the code in the same tool. In this step, we want to store our Unity source code in GitHub.
Go to GitHub, sign up, and create a private repository.
Download Git, and navigate to your Unity project folder.
Configure Git with your credentials:
git config –global user.name “<username>”
git config –global user.password “<password>”
Code language: HTML, XML (xml)
We will need a .gitignore file, which defines the files that should not be uploaded to the repository by Git. You can download a Unity specific gitignore file:
curl https://www.toptal.com/developers/gitignore/api/unity -o .gitignore
Code language: JavaScript (javascript)
Then, add a remote repository to your newly created GitHub repository:
git remote add origin https://github.com/gamebackenddev/<your_repository>.git
Code language: HTML, XML (xml)
Thereafter, stage and commit your code changes, and push to the remote GitHub repository:
git init
git status
git add .
git commit -m “Initial commit”
git remote add origin https://github.com/gamebackenddev/<your_repository>.git
git push --set-upstream origin master
Code language: JavaScript (javascript)
Any changes in the future should also go through this staging, committing, and pushing process. You can also use other non-CLI tools, for example, a Visual Studio Code extension, to carry out these processes.
Unity Activation
This activation step is Unity specific and mandatory as we want to build our game with GitHub Actions. We will use GameCI, which is a fantastic and completely free initiative as it allows us to create CI workflows easily.
Create a folder .github/workflows, where we will put the workflow files. You can have multiple workflows with each containing multiple jobs, and each job can also contain multiple steps.
Create a file, activation.yml, and copy the following content in it:
name: Acquire activation file
on:
workflow_dispatch: {}
jobs:
activation:
name: Request manual activation file ?
runs-on: ubuntu-latest
steps:
- name: Request manual activation file
id: getManualLicenseFile
uses: game-ci/unity-request-activation-file@v2
- name: Expose as artifact
uses: actions/upload-artifact@v2
with:
name: ${{ steps.getManualLicenseFile.outputs.filePath }}
path: ${{ steps.getManualLicenseFile.outputs.filePath }}
Code language: JavaScript (javascript)
This workflow will run on Ubuntu, and then we will start it manually as we set the workflow_dispatch. It will upload an ALF file as an artifact to GitHub.
Don’t forget to stage, commit, and push this workflow to your GitHub repository.
In GitHub, go to your repository, click on Actions, and under the Workflows, you can see the Acquire activation file workflow. Now click on Run workflow.
You can also generate this ALF file with Unity on your local machine, however, you will then see later “Machine identification is invalid for the current license.” failure.
Download the ALF file from GitHub to your local machine. You will find it if you click on the manually triggered workflow in the Artifacts window.
Go to the Unity License Activation page and upload the earlier downloaded ALF file. After filling in the form, you will get a ULF file.
Create a new secret in GitHub, under Settings > Secrets > Actions > New repository secret, called UNITY_LICENSE. Copy the content of the ULF file and add it to this secret.
Building Your Client
In this step, we will build our WebGL client. Create a new workflow, such as BuildClient.yml, and copy the following code into it:
name: Build WebGL Client
on:
workflow_dispatch: {}
jobs:
buildClientForWebGL:
name: Build Client for WebGL
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v2
with:
path: Library
key: Library-WebGL
- name: Build
uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
targetPlatform: WebGL
- name: Upload
uses: actions/upload-artifact@v2
with:
name: mygame
path: build/WebGL
We will again use Ubuntu to execute the steps and start the workflow manually. You can also exchange the workfload_dispatch to trigger this workflow after each push to the remote repository.
In the first step, we checked out the code from the repository. The caching helps to speed up the build, we cache the Library folder. In the build step, we pass the license and configure the target platform. You can also add automated testing to this workflow. And finally, we upload the result as an artifact so that we will be to download and test it.
Again, let us stage, commit and push this code to our repository, and run the workflow manually. If everything went fine, download the output file.
To test the built WebGL game you will need a local webserver. Extract the downloaded ZIP to a folder, and start the following command from that folder:
python -m http.server 8080
Code language: CSS (css)
Type in the browser localhost:8080.
Conclusion
In this first part, we created a simple networked game, configured a repository for the source code management and we also defined a CI workflow that builds our game. In the next step, we will implement the CD part of our workflow, which will help publish the WebGL game to Azure.