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.

5 (3) · 3 Reviews

Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Placing Temporary Construction Tiles

Next, you’ll start adding some functionality to the new BuildRoadAsync method. You do this the same way you would add steps to any regular method.

For starters, you’ll place a construction tile at the location where the road will be. In BuildRoadAsync, add the following line to instantiate constructionTilePrefab at the location the user clicks.

var constructionTile = Instantiate(constructionTilePrefab, buildPosition, Quaternion.identity, levelGeometryContainer);

Now that you’ve defined the first step of building a road, it’s time to call the method. You call asynchronous methods the same way you call any other method. In the BuildStructure method, add the following line after roadProperties gets defined and set:

var buildRoadTask = BuildRoadAsync(roadProperties, buildPosition);

buildRoadTask will now hold a reference to the returned Task from the BuildRoadAsync method. Save your script.

Test if this first step worked. Go to Unity and click Play. In play mode, select one of the roads from the build menu and place it in the game world. If everything is working correctly, you’ll see the construction tile spawn where you placed the road.

Placing construction tiles for roads in Wenderlich-Topia

Your code is still running synchronously. That’s because the program doesn’t know to wait for a task’s completion to run further steps.

Adding await to Start Running Asynchronous Code

The final component for writing basic asynchronous tasks is await. Using it with a Task tells the program to return to executing the synchronous code that called the async method. This synchronous code is therefore not blocked, and can continue running at least until it requires the returned Task code. The async Task will continue running in the background while the rest of the synchronous application code runs. Once the async Task method completes, the code after await will resume executing.

The above might sound confusing at first, so read it a few times. Or read this quote from the Microsoft await operator documentation:

The await operator doesn’t block the thread that evaluates the async method. When the await operator suspends the enclosing async method, the control returns to the caller of the method.

In Wenderlich-Topia, roads will take some time to build, yet the player will expect to be able to continue interacting with the game while the road is under construction. The code will await the road’s completion so that the rest of the game can continue running uninterrupted.

Once the road building task is complete, the asynchronous method resumes and does the following:

  • Removes the temporary construction tile.
  • Spawns the final road tile.
  • Plays a UI effect displaying the cost of the road.

To start running asynchronous code, you’ll await a call to Task.Delay(int millisecondsDelay) in the BuildRoadAsync method to allow a time delay of 2.5 seconds after the constructionTile spawns. Add the following to the end of the BuildRoadAsync method.

await Task.Delay(2500);

Now, any subsequent code in BuildRoadAsync will not run until the 2.5 second timer is up.

Next, remove the temporary construction tile and spawn the final road tile. To do this, add the code below after the await Task.Delay(2500); line in the BuildRoadAsync method:

Destroy(constructionTile);
Instantiate(roadProperties.completedRoadPrefab, buildPosition, Quaternion.identity, levelGeometryContainer);

The full road construction cycle is now in place. Next, you need to ensure that BuildStructure knows when the road is finished so it can show the relevant UI effects. The UI effect for showing the total build cost is already included in the Starter project. The UI Manager handles this responsibility for you.

Add the code below to the BuildStructure method, after the call to BuildRoadAsync, which you added previously:

await buildRoadTask;
uiManager.NewStructureComplete(roadProperties.roadCost, buildPosition);

The game will now wait for the BuildRoadAsync to complete and then show the cost of the road as a UI effect.

Go to Unity, enter play mode, and place some roads in the game world.

Building roads in Wenderlich-Topia

You’ll see the construction tile appear. Then, after 2.5 seconds, the final road will appear, followed by the UI effect showing the cost. Notice that while the road is being built, you can still interact with the game and even build multiple roads at once if you’re fast enough. :]

Quickly building roads in Wenderlich-Topia

Further Asynchronous Programming Concepts

In the following two sections, you’ll learn some more asynchronous programming features by building houses. In the end, residents of Wenderlich-Topia will have a place to live.

To build a house, implement the following steps:

  1. Place a temporary construction tile where the house will get built.
  2. Build a house frame.
  3. Build a roof.
  4. Build a fence.
  5. Finalize the house.
  6. Play UI effect to display final cost.

Steps 2-4 are individual tasks, but they won’t happen in sequence. Once you construct the frame, you can also construct the roof and fence at the same time. Once both the roof and fence are complete, you can finalize the house.

Returning Values From Tasks

Remember the three types of return values you learned about earlier? In the following section, you’ll learn how to use the third type, Task<TResult> to return values from Tasks.

One key difference between building houses and roads in Wenderlich-Topia is the cost. The player won’t know the final cost of building a house at the time of construction, but they will know the estimated cost shown on the Build House UI button.

In ConstructionManager.cs, define a BuildHouseAsync method to schedule individual tasks. Each task calculates the task cost by multiplying the task completion time by a wage value. At the end of BuildHouseAsync, you’ll:

  • Sum the cost of all tasks.
  • Return the total cost to BuildStructure.
  • Display the total cost UI effect.
Note: For this project, each task will take a random amount of time between 1.5 and 3.25 seconds. The wage is set at $30.

You’ll now implement the method that returns Task<TResult>. This return type has the same features as a standard Task, with the important benefit of being able to return a defined value within the angle brackets. Like a standard non-void method, async Task<TResult> must return a value of the defined type.

Now, define the BuildHouseAsync method that returns a Task<int>, as the total house cost will be represented as an integer type:

private async Task<int> BuildHouseAsync(HouseBuildProperties houseBuildProperties, Vector3 buildPosition)
{
    var constructionTile = Instantiate(constructionTilePrefab, buildPosition, Quaternion.identity, levelGeometryContainer);

    return 100;
}

The method spawns the temporary construction tile and returns a value of $100. The value is temporary. You’ll calculate the actual value of the house once it’s finished. Too bad because a $100 house would definitely be a steal.

Next, in BuildStructure, make a call to BuildHouseAsync after you set houseProperties. Store the result as a Task, then wait until it’s complete:

var buildHouseTask = BuildHouseAsync(houseProperties, buildPosition);
await buildHouseTask;

Next, in the same method, calculate the cost of the house by accessing Result on buildHouseTask. You’ll use that value to display the UI effect on the screen.

var houseCost = buildHouseTask.Result;
uiManager.NewStructureComplete(houseCost, buildPosition);

Return to Unity, enter play mode, and attempt to build a new house in the game world. First, you’ll see the temporary construction tile placed on the map, immediately followed by the UI effect displaying $100, the placeholder cost.

Placing temporary tiles for houses in Wenderlich-Topia

Johnny Thompson

Contributors

Johnny Thompson

Author

Srikar Mutnuri

Tech Editor

Yuliya Goldshteyn

Editor

Julia Zinchenko

Illustrator

Sean Duffy

Final Pass Editor

Tammy Coron

Team Lead

Mauro Fuentes

Topics Master

Over 300 content creators. Join our team.