Introduction to Asynchronous Programming in Unity
Dive deeper into the world of asynchronous programming in Unity by creating a fun town-builder game. By Johnny Thompson.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Introduction to Asynchronous Programming in Unity
35 mins
- Getting Started
- Setting Up the Starter Project
- Advantages of Asynchronous Programming
- Writing Basic Asynchronous Code
- Defining the async Keyword
- Building Structures With Task
- Placing Temporary Construction Tiles
- Adding await to Start Running Asynchronous Code
- Further Asynchronous Programming Concepts
- Returning Values From Tasks
- Awaiting Multiple Tasks
- Building a House by Parts
- Cleaning up Construction
- Improving Your Asynchronous Code
- Cancelling Tasks
- Cancelling a Task Efficiently
- Catching Exceptions
- Choosing Asynchronous Programming vs. Coroutines
- Advantages of async Over Coroutines
- Deciding When to Use Coroutines
- Where to Go From Here?
Catching Exceptions
When you pressed Escape, you may have noticed that an exception showed up in the debug console. This is because whenever a task gets canceled at runtime, an exception is thrown by CancellationToken
.
In this section, you’ll learn how to catch these exceptions and implement your own custom error handling for canceled tasks. This is easy to do using CancellationToken
.
In the BuildStructure
method, surround the calls to BuildRoadAsync
and BuildHouseAsync
in a try...catch
block. Here’s what the code should look like once wrapped in a try...catch
block for the BuildHouseAsync
Task. (Don’t forget to do the BuildRoadAsync
one too):
var buildHouseTask = BuildHouseAsync(houseProperties, buildPosition, cancellationToken);
try
{
await buildHouseTask;
var houseCost = buildHouseTask.Result;
uiManager.NewStructureComplete(houseCost, buildPosition);
}
catch
{
Debug.LogWarning("Building House Cancelled");
}
The task is now awaiting inside try
. If it completes successfully, the remaining code in try
will run, displaying the appropriate UI effect. If Task
throws an exception through CancellationToken
, the code inside catch
will run instead. For simplicity and the purposes of this tutorial, a warning is printed to the console. For your own project, you might want to handle this in a better way.
Go back to Unity, enter play mode, and test your exception catching. Cancel a house halfway through its building process. Rather than a system-generated error, you now see the custom warning you printed through code.
Choosing Asynchronous Programming vs. Coroutines
Now that you’ve learned about C# asynchronous methods, you might have found similarities to coroutines in Unity. However, while they are similar, key differences between the two make each of them work better in certain situations.
Coroutines are a type of method that allows code to be executed over a stretched period of time. Often, programmers use coroutines for moving GameObjects
, setting countdown timers or fading textures between colors. Basically, they suit gameplay programming quite well.
You can learn more about how to use coroutines in the official Unity documentation.
Advantages of async Over Coroutines
One of the biggest advantages of async
over coroutines is its ability to return values. For example, in Wenderlich-Topia, the cost of building the house is calculated asynchronously while the house is being built. Once the house is complete, the code returns the total cost of the house’s value, and the result is available in the Task
result variable. Coroutines can’t return any values.
Async
methods can also run on threads that aren’t the main thread. This means they can continue working on complex tasks without impacting performance on the main thread.
While coroutines also run in the background, they run on the main thread. This means they could impact the performance of the game if they’re doing complex operations.
Finally, a major advantage of async
is that many external libraries and APIs also use async
. This makes it easy to integrate others’ asynchronous methods into your code.
Deciding When to Use Coroutines
Coroutines are best used for set it and forget it scenarios when you need to execute code over time but don’t need any results and don’t want to manage your code. Once the coroutine is complete, it can trigger some additional behaviors to happen. (An example of this being the one described earlier – changing the color of a GameObject over time).
Additionally, because coroutines are a Unity feature, they’ll stop when the program ends. You won’t have the same problem with asynchronous code, which would continue running even after the application stops. Unity handles this cancellation for you. As you saw before, the Unity engine does not handle the cancelation of async Tasks.
Coroutines also integrate well with other Unity features and a game’s update loop. With coroutines, you can simply call yield return break;
to halt a method’s execution and return to that point in the method on the next frame. Put a yield
inside a for
or while
loop and you can make things move or change over time.
You can achieve similar behavior with async
in Unity, but of course, being a C# language feature, it wasn’t built with this use case in mind, so the code is a bit messier when trying this kind of scenario with Unity.
Where to Go From Here?
You can use the Download Materials button at the top and bottom of this tutorial to download the starter and final projects.
Now, you hopefully understand how to use asynchronous methods in Unity and know when to use them (and when not to).
To increase your skills, practice implementing what you learned in some of your own projects.
As a next step, you could graduate to integrating with other asynchronous features such as Unity’s Addressable Asset System. This asynchronous way of loading assets into your game is preferable to loading assets from the Resources folder. For more information on the Addressable Asset System, check out Introduction to Modding Unity Games with Addressables from raywenderlich.com.
You can also learn about writing multithreaded code using something like Unity’s C# Job System. Check out the raywenderlich.com tutorial Unity Job System and Burst Compiler: Getting Started on how to create a wave generator using Unity’s C# Job System.
We hope you enjoyed this tutorial. If you have any questions or comments, please feel free to join the forum discussion below!