Unity Async Await - Make Your Game Run Smoother!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video i would like to talk about the asynchronous programming so running an operation on a separate thread when we use unity in our game we have an operation that takes a very long time and we run it on the main thread which is controlling how we perceive our game this is responsible for driving those robots and for me shooting so let me go to the robot and i'm invoking the operation using the h key and as you can see everything was frozen for a while again everything was frozen and if you see in the console it took three seconds to perform the operation let me show you the code that i'm using so this is a simple perform calculation method that i use in the update when i press h key i am invoking a calculation we loop through the 2d array of float values and we assign mathf.pearly noise value to each of those to simulate for example if we were creating an infinite world and we were calculating the height map of our terrain so what is going on in our game where our game is running on a main thread which is responsible for showing the graphics of our game and all this stuff that the player can see when we run our code that requires a lot of computational power and takes a long time to perform the operation it is blocking the main thread so that our game cannot really be updated because all the resources available are taken by this method that we call and only after the method is done so we experience this freeze for about three seconds we can resume our game and we can see that our game starts running so instead of running our operation on the main thread we want to do something else we want to run our main thread with only our game in mind and when we want to perform the operation we want to introduce a new thread which will take care of performing this operation so basically when we want to perform the operation we send the information from the main thread to start a new thread or to perform the operation on an existing thread nevertheless we want to perform the operation on another thread and not on the main thread so now our game can perform as it does while that other thread is performing the same operation for the same times of about 3 seconds and only after it finishes it should inform our thread that it has received or it has sent the information that we have requested back to it so that now if we can do something with those informations on our main thread now the benefit of this approach will be that we can have our game playing as it should it doesn't speed up the process but it just unloads our main thread from performing this work that takes some time okay so let's see how we would implement it in our unity project so a good idea to fix this issue would be to run this calculation on a separate thread and wait for the result until it is ready now in c sharp we have a task library that gives us a really easy access to asynchronous programming so to starting a separate thread the task class represents a single operation that does not return a value and that usually executes asynchronously and we have those tasks objects that execute asynchronously on a thread pool so on a separate thread rather than synchronously meaning on the main thread of the application and let's see the example here so here is a quick example basically what we need to do is call our method and add to it a keyword async and then when we want to run our code we wrap it in the task.run and we use the lambda expression if you are not familiar with the lambda expression you can check out my other tutorial about it the link should be in the top right corner of the video and we call await keyword so that we await the result before we continue with the rest of this method which is here empty okay i'm in the async test script and i would like to modify the perform calculation method to be run asynchronously so i'm going to copy it i'm going to paste it below and i'm going to rename it to be perform calculation async first of all we need to add the async keyword before the name of the method so i'll call async okay now it is showing me that async method lacks a weight operator so the await operator is when we want to await an execution of some code so this is our code that we want to await basically this code so what i will want to do is call var result will be equal to task and we do not have it so right click quick actions and we need to be using system.threading.tasks library it will be imported at the top and i have this using debug equals debug engine. debug because i'm using the system.diagnostics to measure the time of the execution of this using the stopwatch so that we know how much time it took to perform this operation in any case we have this task we need to add a dot run and this will run the code that we pass here as the action delegate again check out the other video to understand what our delegates and we are going to pass here this code so it will be executed on a separate thread so we are going to create a laptop expression we are not going to take anything uh equal sign and greater sign so this is the lambda expression so we do not take anything and we want to perform this body of a method that we are going to pass here so all we need to do is cut our current code that blocks our main thread and pass it to our run lambda expression okay so this is our code now as you can see we have this map values that we calculate so i will want to return it so i just add return and i will call the map values okay but that's not everything this would simply run this task and continue invoking this code below so if i save it and if i call this code inside our get key in the update you will see that we save it let's go back to unity okay i will play the game and you will see that if i press h the operation took 0 milliseconds so this is amazing well not exactly because we were not awaiting our thread so the thread was performing its operation and we never received the values from it so we are calling this an icy operation but in reality we are never awaiting the result of our thread so this result is never filled so what we will need to do is add a wait before we call the task dot run and now this operation will be performed and only when it completes and returns this map values we will perform this operation here so additionally what we could do is call debug dot log and since our task if we drag our mouse over it will return a task of float to the array we can call debug.log we can call size of 2d array and let's add to it our result dot get length zero and we are going to add plus result get length one okay so now only when the task has finished running on a separate thread and returned our map values we are going to call those two debug.log statements and again it will only work if we have our method with the prefix a sync added or keyword async added before the name of the method so in its definition okay so let's go back to unity okay let me press play and now we can move and shoot and if i press h we have the message age was pressed we can still move and shoot and after some time we are receiving the data so size of the 2d array is 10 000 and as you can see in our async test the data the size of the data is said to be 10 000 so it is the correct size returned by our thread and now i can go further find our enemy and press h to load the data and it is all working fine and after some time i'm receiving the data from our separate thread so that's basically how you would run your operation asynchronously to unblock the main threads so you can perform some calculations or data equation or procedural generation on a separate thread now one more important thing about our threads is that they run and they are not stopped by our unity let's play or pause button so if you press play now i'm going to press h to calculate our data i'm going to escape and stop the game and as you can see it still has printed our result so let me show you again i'm going to press escape now to be able to use mouse i'm going to press h and exit the game and as you can see we are not playing but still our thread is printing the data so this is a bit problematic because we now cannot stop our work on the threads when we stop our unity so how can we deal with that so again let's take a look at the documentation and task cancellation needs to have something called cancellation token source so let's implement it in our code and let's see how we can stop our code from performing the operation on a separate thread using this cancellation token source okay so i will create a variable at the top in our class cancellation token source again we need to use right-click quick actions and we should have the cancellation token source using system dot threading let's call it token source okay and let's create it in our start method so let's call start and we're going to call token source equals new translation token source now we need to pass this token source or other is token to our task so after we call our task.run as the second parameter we can pass the cancellation token so let's call token source dot token and this is passed now as a parameter to our thread now to use it i will call here when we are looping through this for each loop if our token source dot is cancellation requested what we can do is simply return our map values for example and again let's copy this code and when we finish this task we are awaiting it if this is called we can simply return from this method and not perform the further code down the line so now last thing is how can we call this token source to be cancelled what we can do is call our on disable for example and on disable we can call our token source dot cancel and this should cancel the task that we have run on our separate thread so maybe let's debug.log and a message that we have stopped so task stopped before we returned from this method and now if we go to unity okay i'm going to press play again press escape so that i have mouse ready i'm going to press h stop the game and as you can see the task was stopped so now we have a safe way to stop our asynchronous operation if we desire to if we do not want to wait or if we are simply debugging the code now in the next video i would like to explore the topic of running things in parallel and using the unity job system versus using the parallel library from the task library from the c-sharp language and that's what we are going to talk on in the next video until then leave a like subscribe and i will see you in the next video and if you want to support the channel you can do it by joining the patreon the link will be in the description take care
Info
Channel: Sunny Valley Studio
Views: 33,205
Rating: undefined out of 5
Keywords: Unity asynchronous programming, Unity async, Unity await, Unity Task Run, c# asynchronous, c# async await, unity running separate thread, unity asynchronous, sunny valley studio, c# task, Unity C# How to use Async and await to create Tasks, Unity C# How to use Async, unity how to use awake, how to task, how to async await, gamedev, indiedev, game development, indie game development, sunnyvalleystudio
Id: gxaJyuf-2dI
Channel Id: undefined
Length: 13min 17sec (797 seconds)
Published: Fri Apr 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.