This post has been updated in July 2022 to introduce some fixes to the codemagic.yaml file in the sample project.
TL;DR: Collaboration between Unity developers and artists can be enhanced by adding some automation tools. For example, using automatic build triggering once a new asset is added allows the artist to see how it looks in the game without bothering the developer, which reduces waiting times and context switching. Not much tooling is needed to set this up — you can use any Git provider for version control, Slack for notifications, and a Codemagic pipeline with a webhook that triggers once a new branch with a specific name is added.
This article is written by Mina Pêcheux
Let’s see how we can help artists and game developers work together more efficiently with the support of some automation.
Games make great projects because they mix plenty of skill sets and bring together various areas of expertise. For example, the heart of any game project is developers and artists. To collaborate effectively, they need to be able to seamlessly communicate and easily share assets between teams. However, this can be pretty complex in practice because neither artists nor devs have the time to manage the entire lifecycle of all resources from design to creation and, eventually, implementation.
So, in this article, we’ll discuss how we can use tech to ease collaboration and achieve continuous art-to-dev communication. Specifically, we’ll cover the following:
- Why automating the dev/artist interface is beneficial
- The basic gist of this automation
- How to set it up for a Git-versioned Unity project using Codemagic
Why you should automate the management of your game assets
Let’s say you’re a game artist working on a small Unity project. There is no infrastructure yet, no big DevOps team, and no super-solid asset management pipeline. This means that whenever you create a new 3D model, 2D sprite sheet, pixel-art animation, or any other asset for the product, you’ll have to go through a time-consuming manual integration phase. Someone (either you or a dev, depending on the team members’ skill sets) will have to take the new file, import it into the Unity project, rebuild the prototype with this change, and check that everything works properly.
In this case, you’ll want to have regular feedback on whether the assets you are making are valid and valuable for the game, but preparing a new build of the product with your updated resource takes time and effort. People on your team are already drowning in their to-dos and don’t want to spend minutes redoing all the build and publication steps every time an image or a model changes. These tasks are bottlenecks because all of the work is done manually!
But what if this integration was automated? What if there was some process in place such that whenever you published a new asset, it would be directly imported into the Unity game, a new prototype would be built, and then you would get a link on your team’s Slack in the following half-hour to download and run the new game version and check that your asset works properly?
Note: This automation often also relies on some tools that help with the standardization/sanitization of your asset names and paths. How to handle this asset nomenclature is a topic for another day, but it’s important to remember that, generally speaking, your pipeline is only as robust as it is “ready to use”. You should not have to think every time you do a task. Instead, everything should be prepared so that the context is taken care of and you can focus on the real work — otherwise, you’ll have to tweak and fix things all along the way, and you’ll lose all the benefits of the automation! 🙂
How can you “integrate your artists” into the dev workflow?
OK — our goal is to automate the build and delivery of our game prototypes so that artists can get new versions of the product with their asset in it without annoying the dev team. How can we accomplish this?
Luckily, this concept of “version” is already a fundamental building block of a very widely used type of tool: version control systems. Git is the most famous of these, though there are some alternatives in the world of game development, such as Perforce or Plastic SCM.
Note: By default, Unity is not really tuned to use Git. If you’re not familiar with how to set up a solid and sound Git versioning workflow for your Unity projects, don’t hesitate to check out this other article I wrote on the topic a few weeks ago. 🙂
Even small teams like the one in our hypothetical scenario most likely use some kind of version control system to help synchronize, publish, and update all the code and assets — therefore, why not rely on this basic element of any game dev project and improve it to create our automation?
Essentially, the idea is to “hook into” the system of commits and branches that version control systems like Git offer and use them to trigger additional processes — in our case, the building and deployment of our prototype!
This way, whenever I, as an artist, change an asset at a specific point in the workflow, the rest of the chain will automatically run the required steps to create the associated game prototype and share it with me.
This way of doing things has several advantages:
- It lets you precisely control what triggers the flow and updates at a very granular level
- However, it takes all this integration granularity out of the hands of the devs and thus lightens their load
- At the end of the process, we’ll see that it also helps compartmentalize the info since it can be configured to notify only a few selected individuals
In other words, using a tool that our team is most likely already working with (Git or equivalent), we can step up our game to efficiently update and deliver new prototypes to the team by keeping the right people in the loop while avoiding disrupting anyone’s day by forcing them to switch tasks.
Combining Git and Codemagic to automate our Unity prototype builds
Suppose that, once again, I’m creating some game art for my team. Right now, I’m working on a set of tiles for our awesome platformer game Super Jump! (Don’t worry, it’s not a real game, so it can have a lousy name.)
At the moment, some of the game’s core mechanics have been coded: You can move the player left and right, and you can jump.
The next item on the team’s to-do list is to start a bit of the level design. I’ve come up with a nice 3D asset (made in Blender) to replace those basic cubes!
Now, how can I integrate this asset into the game?
Let’s see how we can set up our automation using Git for versioning and triggering, Codemagic for building and deploying, and Slack for notifying end users…
Important disclaimers:
- The “game” I’m showing here is obviously just a sample project to show the Git + Codemagic + Slack stack — the code I’m sharing is crude and probably not fit for real productions… 😉
- I’m assuming that there is someone on the team who can handle the level design, i.e., a person skilled with Unity who prepares some placeholders for the assets and sets up the import settings. So my job as a game artist is to replace the placeholder asset files, which will be automatically used in the Unity scenes instead of the primitive/temporary models.
I’ve been told to add my assets in a specific “Imports” folder (optionally, a subfolder if needed) and replace the placeholder files with my own assets. In this case, I’ll replace atile-001.fbx
FBX 3D tile asset: The placeholder is a simple cube mesh, and I need to replace it with my own dirt and grass tile model.
Of course, the second point is a pretty big assumption. In a real-life scenario, assets streamlining would need to be configured better. For example, it could rely on Unity’s Preset Manager or AssetPostprocessor to ensure the game art is properly imported and integrated into the Unity project! But since my focus here is on automation, I’ll leave that for another day. 😉
So, in the following sections, I’m going to take on various roles in the small team: I’ll take you through how to set up the automation as a “DevOps” expert and how game artists can then benefit from it.
DevOps: Preparing the automated setup
Part 1: Setting up Codemagic
Important note: Deploying Unity apps with Codemagic requires a Unity Pro or Plus license!
Codemagic is an online tool that allows you to quickly and easily build various kinds of projects, including Unity games, for any target platform you want (e.g., Windows, Mac, Android, iOS).
In case you are not a Codemagic user yet, you can sign up here:
One great thing about Codemagic is that it’s very easy to set up and integrate into your Unity project. It only takes three steps.
- First of all, each Git project (like my Unity game here) needs to be associated with a Codemagic app. To create a new app, just go to your Codemagic dashboard and click the “Add application” button in the top-right corner:
Also, Codemagic relies on a Git provider like GitHub, GitLab, or Bitbucket to fetch your code and track all the available branches or tags to build from. So choose the right Git provider and connect the Git repo from which to get the codebase:
- Then, go to your app settings, click on the “Environment variables” tab, and define the required Unity-related variables as explained in the Codemagic docs:
- Finally, all that’s left to do is add two files to your Git repo:
- The
codemagic.yaml
configuration file in which you define the automation workflow - A
Build.cs
script so that the Codemagic pipeline can build your Unity game programmatically by running Unity via the command line
In our example, I’ll automate the building of my Unity game as a Mac .app
, so I need the following Build.cs
file (for other platforms like Android or iOS, you can check out the Codemagic docs):
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class BuildScript
{
[MenuItem("Build/Build Mac")]
public static void BuildMac()
{
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.locationPathName = "mac/" + Application.productName + ".app";
buildPlayerOptions.target = BuildTarget.StandaloneOSX;
buildPlayerOptions.options = BuildOptions.None;
buildPlayerOptions.scenes = GetScenes();
Debug.Log("Building StandaloneOSX");
BuildPipeline.BuildPlayer(buildPlayerOptions);
Debug.Log("Built StandaloneOSX");
}
private static string[] GetScenes()
{
return (from scene in EditorBuildSettings.scenes where scene.enabled select scene.path).ToArray();
}
}
I need to add this file to my Assets/Editor
folder.
The Codemagic workflow for building my Unity app is then configured thanks to a codemagic.yaml
file like this one, which is placed at the root of the Git repo:
workflows:
unity-mac-workflow:
# Building Unity on macOS requires special instance type which is available upon request
name: Unity Mac Workflow
environment:
groups:
# Add the group environment variables in Codemagic UI (either in Application/Team variables) - https://docs.codemagic.io/variables/environment-variable-groups/
- unity # <-- (Includes UNITY_SERIAL, UNITY_USERNAME, UNITY_PASSWORD)
vars:
UNITY_BIN: ${UNITY_HOME}/Contents/MacOS/Unity
scripts:
- name: Activate License
script: $UNITY_BIN -batchmode -quit -logFile -serial ${UNITY_SERIAL?} -username ${UNITY_USERNAME?} -password ${UNITY_PASSWORD?}
- name: Build
script: $UNITY_BIN -batchmode -quit -logFile -projectPath . -executeMethod BuildScript.BuildMac -nographics
artifacts:
- "mac/SuperJump.app"
publishing:
scripts:
- name: Deactivate License
script: $UNITY_BIN -batchmode -quit -returnlicense -nographics
This workflow relies on several blocks to properly set up the remote Codemagic build machine and run the Unity process on it:
- First, we either re-inject the environment variables that we previously defined in our app settings thanks to the env var groups (like the
unity
group here) or add them directly as key-value pairs (like theUNITY_BIN
variable here) - The scripts are the steps to chain in your workflow; in this example, we activate the Unity account and build the game as a
.app
thanks to ourBuild.cs
file (and, more precisely, the static functionBuildMac()
that we defined in this class) - The build is stored as an artifact,
mac/SuperJump.app
- Finally, we reach the publishing phase, during which we clean up the computer and handle any distribution/notification processes
For now, this workflow simply builds my Unity game as a .app
file and provides me with the resulting file in my Codemagic dashboard. I can start a manual build to check that everything works:
You can see that after the workflow runs successfully, it provides me with a .zip
archive that contains my .app
Unity game prototype:
Part 2: Triggering builds from commits
The next step is to set up these builds to run automatically when a game artist updates an asset!
Codemagic actually has a feature that is meant to do exactly this: the “triggering” configuration. By adding this triggering
key in your codemagic.yaml
file, you can tell the tool to react to specific Git events, such as a push, tag, or pull request, and start a new build when they occur.
To better control your builds, you can also define some branch or tag patterns to specify the names to look out for.
For Super Jump, my goal is specifically to automate the integration of game art. I don’t want to automate anything else for now. So I’m going to decide that:
- All my game artists will publish their changes on Git branches with names that are prefixed with
feat-art/
(because they are creating an “art feature”) - Any time an artist pushes one or more commits to the repo on such a branch, a new build is triggered
We can do this by adding the following triggering
block to our codemagic.yaml
file:
workflows:
unity-mac-workflow:
# Building Unity on macOS requires special instance type which is available upon request
name: Unity Mac Workflow
environment: ...
triggering:
events:
- push
branch_patterns:
- pattern: 'feat-art/*'
include: true
source: true
scripts: ...
artifacts: ...
publishing: ...
After updating and committing this file to the Git repo, if we go back to our Codemagic app settings, we can see in the “Webhooks” tab that there is now a new hook available — it has a unique URL that we can copy using the button on the right:
To actually trigger this hook with Git pushes, however, we also need to set up some things on the GitHub side. More precisely, we have to go to our GitHub repository settings, select the “Webhooks” section, and add a new webhook:
Here, we can copy our Codemagic hook URL in the “Payload URL” field. (Note that Codemagic supports both the application/json
and application/x-www-form-urlencoded
formats, as explained in the docs.)
Also, in my example, I’m only reacting to pushes, so I can leave the default events configuration settings. But if you want to listen to more events, go ahead and use the radio buttons at the bottom to select the ones you are interested in. 🙂
Once you’ve added the webhook to your GitHub repo, it will be listed and ready to run the next time you do a git push
!
Part 3: Adding the Slack integration
The final thing I want to automate is the artifact delivery. Remember the publishing
block in the YAML configuration file we mentioned earlier? It is used for not only cleanups but also “artifact post-processing,” such as distributing the build artifact(s) to a few selected individuals.
Here, I’m only going to discuss the Slack integration, though Codemagic offers various publishing integrations, such as Google Play and Firebase App Distribution.
Again, this process is pretty straightforward!
First, we have to enable the Slack integration for our Codemagic account; this can be done at either the user or team level. You can take a look at the docs for more info on this, but basically, you’ll have to:
- Navigate to your user/team settings, and go to the “Integration” section:
- Authorize Codemagic to connect to Slack (be sure to choose the right workspace):
- Once it’s linked, you can, of course, disconnect the Slack workspace to reconnect to another from this settings panel:
For this sample demo, I’ve temporarily connected my Codemagic account with my personal Slack workspace. I also prepared a public channel where I’ll get my Super Jump build notifications: #test-codemagic-integration
. I can see both the new “Codemagic app” and the channel in my workspace:
Note: If you want to publish to a private Slack channel, you’ll need to invite the Codemagic app to the channel so that it has access; to do this, write @codemagic
in the channel. If access to the private channel is restricted by Slack admin rights, it will have to be changed manually — otherwise, publishing to that channel will not be possible.
In a real-life scenario, we could invite just the game artists to this channel so that only they get notified about the builds from the Codemagic workflow (that are triggered by pushes on the feat-art/*
branches).
Now, we can update the codemagic.yaml
file and extend the publishing
block with a slack
key. We simply need to specify the name of the channel to notify on — and, optionally, some other settings, like enabling/disabling notifications on build start, success, or failure:
workflows:
unity-mac-workflow:
# Building Unity on macOS requires special instance type which is available upon request
name: Unity Mac Workflow
environment: ...
triggering: ...
scripts: ...
artifacts: ...
publishing:
scripts:
- name: Deactivate License
script: $UNITY_BIN -batchmode -quit -returnlicense -nographics
slack:
channel: '#test-codemagic-integration'
notify_on_build_start: true # To receive a notification when a build starts<
Note: If you want, you can even auto-generate a changelog and put it in a release_notes.txt
or release_notes.json
file at the root of the Git repo to have Codemagic send it directly when publishing, along with the artifacts! 😉
With all that prepared, we are now ready to try this entire toolchain as a game artist… If all goes well, we should be able to publish our new asset version to replace a placeholder and, after a little while, get the updated game prototype in our Slack #test-codemagic-integration
channel!
Game artist: Working in an automated environment!
I’m going to assume that, as an artist, I’m not really into writing command lines in a shell. So instead of using Git in the terminal as I usually do, this time, I’ll discuss how to use GitHub Desktop for a full GUI experience! 🙂
GitHub Desktop is a well-known and widely used Git GUI client, a software application for interacting with Git projects and repositories via a visual interface rather than command lines. It’s not the only one out there, but it’s easy to use and will work perfectly with our public GitHub repo for this demo project.
Note: This software doesn’t work on Linux, however — for this OS, you can take a look at Git Extensions, which is pretty similar.
After downloading and installing the software, the first time you open it, you’ll be asked to connect it with your GitHub account so that it can fetch and use your online GitHub repositories. Once that’s done, you’ll be presented with a basic dashboard with a list of your available repositories. You can choose which one you want to work with this time:
Note that you can also add a local Git repo if it’s already on your computer.
Here, I’m going to be using my “Unity-SuperJump” GitHub repo, which currently only has a master
branch. The UI shows me the following:
- At the very top, the name of the repo I’m working on and the current active branch
- On the left, a list of current changes
- In the bottom-left corner, a space where I can commit new modifications
At the moment, my repo is “clean” — there are no local changes.
So, let’s say I drag and drop my new tile-001.fbx
asset inside the Imports/Tiles
folder to replace the placeholder cube mesh. I’ll then get a new local change in my repo that appears in the list of changes on the left:
But of course, I’ve been told by the DevOps team members that I shouldn’t commit to master
but rather a branch that has a name starting with feat-art/
! 😉
So I have to create a new branch to do my modifications on. To do this, I just need to go open the “Current Branch” dropdown at the top and then type in the name of my new branch:
The following panels allow me to create the branch and switch to it directly:
Finally, all I have to do is check that I’m on my new branch, toggle the checkbox next to my tile-001.fbx
file to add it to the commit, add a commit message at the bottom, and click the “Commit to feat-art/tiles” button…
And I now have some local changes that I can push to the online shared version of the repo! (Since I just created my branch, I obviously need to publish the branch itself as well, but this still counts as a “push” operation.)
Thanks to all the automation that’s in place, I’ll instantly get a new Slack notification (and the associated message in the #test-codemagic-integration
Slack channel) that tells me a new build has started:
The Slack message even tells me which branch triggered the build and gives me a link that I can follow to see the state of the build. 🙂
After a little while, I’ll get another Slack message that tells me the build is finished and lets me download the .app
artifact directly (in a ZIP archive).
And if I unzip the artifact and start the app, I’ll get my brand-new version of the Super Jump game with my tile asset instead of the cube placeholders. (If Apple gives you a security warning, right-click on the .app
and force “Open”.)
Cool, right? 🙂
Conclusion
As I’ve discussed in previous articles on Codemagic’s blog, automation is key to building a robust production pipeline because it makes sure you focus your efforts in the right place and gives your team more rewarding roles than copy-pasting files or clicking a “Build” button. 🙂
Your automated workflow can even integrate some validation steps upstream of the build so that your code and/or assets don’t break any prior work, and it can have some distribution and QA features downstream to get continuous feedback.
Tools like Git and Codemagic make it straightforward to set up this automation and help you organize your project — and therefore your team — better! 🙂
I hope you enjoyed this tutorial. And of course, don’t hesitate to share your ideas for other DevOps topics you’d like me to make Unity tutorials on! You can find me on Codemagic’s Slack, on Medium, or on Twitter.
You can find the sample project for this tutorial along with the codemagic.yaml
file on GitHub over here. 🚀
Mina Pêcheux is a freelance full-stack web & game developer. She’s also passionate about computer graphics, music, data science, and other topics! She runs her own blog. Alternatively, you can find her on Twitter.
Discussion about this post