Unity Async Await - Make Your Game Run Smoother!

แชร์
ฝัง
  • เผยแพร่เมื่อ 30 ก.ค. 2024
  • In this tutorial want to explain the Async Await Unity workflow so that you can run code on a separate thread to make your game run faster. I will also show you how to stop a task using a Cancellation Token as it is a bit more work than running code synchronously using a coroutine.
    𝗟𝗲𝗮𝗿𝗻 𝗺𝗼𝗿𝗲 𝗮𝗯𝗼𝘂𝘁 𝗨𝗻𝗶𝘁𝘆 𝗮𝗻𝗱 𝗖# (and support the channel) by checking out my video courses:
    courses.sunnyvalleystudio.com/
    𝗛𝗮𝘃𝗲 𝗮𝗻𝘆 𝗾𝘂𝗲𝘀𝘁𝗶𝗼𝗻𝘀? 𝗝𝗼𝗶𝗻 𝘁𝗵𝗲 𝗱𝗶𝘀𝗰𝗼𝗿𝗱!
    / discord
    𝗣𝗟𝗘𝗔𝗦𝗘 support the channel:
    / sunnyvalleystudio
    00:00 Introduction
    00:26 Blocking the main thread
    01:04 What is Main thread
    03:16 Introducing Task class
    04:29 Using Async and await
    10:07 How to stop a Task - Cancellation Token
    #unitycsharp #unity #sunnyvalleystudio

ความคิดเห็น • 89

  • @keelanbowker-obrien2222
    @keelanbowker-obrien2222 3 ปีที่แล้ว +49

    This is honestly a really good tutorial about something that not many people cover. Thanks a lot!

    • @SunnyValleyStudio
      @SunnyValleyStudio  3 ปีที่แล้ว +4

      Thanks for watching!

    • @Axle117mc
      @Axle117mc 2 ปีที่แล้ว

      + It covers the topic of how to actually Cancel a running task since unity doesn't handle it internaly.
      Much love

  • @mementomori7160
    @mementomori7160 3 ปีที่แล้ว +7

    I've found you by accident while I was reading a post on reddit, I'm glad because I was just looking for some tutorials about exactly this. And you're video about lambda expression is really good too, I finally understand it better.
    Subscribed, I'll check more of your videos and I'm waiting for the next one

    • @SunnyValleyStudio
      @SunnyValleyStudio  3 ปีที่แล้ว +1

      Thanks a lot for watching! I am really glad that I was able to help you understand lambdas :)

  • @PsigenVision
    @PsigenVision 2 วันที่ผ่านมา +1

    In my hunt to understand async, your video was an instant addition to my playlist, and the first one I go to when I'm like "wait... how did that work again?"
    That being said, I would be so so grateful if you could maybe follow up this video with an introduction to incorporating UniTask.

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 วันที่ผ่านมา +1

      Awesome idea! Thanks for the feedback. Adding it to a todo list 🙂

  • @PROeloGangsta
    @PROeloGangsta 3 ปีที่แล้ว +1

    Amazing tutorial! Can't wait for parallel topic. Thanks!

  • @vima9046
    @vima9046 2 ปีที่แล้ว +5

    THANKS THANKS THANKS! Superclear and esaustive explanation of an a bit complex argument in an easy way! All teacher should explain like you! Thanks again!

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      I'm glad that you like it. Thanks for watching!

  • @bsdrago
    @bsdrago 10 หลายเดือนก่อน +2

    This video is very good, BUT, deserves an Update with Awaitable class =)

    • @SunnyValleyStudio
      @SunnyValleyStudio  10 หลายเดือนก่อน +1

      Thanks for the feedback! I will definitely make a video about that feature :)

  • @Fatalix3d
    @Fatalix3d 3 ปีที่แล้ว +1

    Thank you, really good tutorial.

  • @devgame
    @devgame ปีที่แล้ว +2

    Very simple and clear explanation, thanks!

  • @Focto
    @Focto 28 วันที่ผ่านมา +1

    Damn, you have such a good visualization, it's ease me too understanding it 👌

    • @SunnyValleyStudio
      @SunnyValleyStudio  20 วันที่ผ่านมา

      I really appreciate that! And I do apologies for a late response 😅

  • @lubba64
    @lubba64 2 ปีที่แล้ว +1

    this literally saved my game thanks so much

  • @cryptoversegirl7751
    @cryptoversegirl7751 ปีที่แล้ว +1

    Two years old video. Still its very useful and i have subscribed to your channel. Looking forward to see many interesting topics!

  • @Eculeus007
    @Eculeus007 3 ปีที่แล้ว +2

    Wow thank you! I think Async can be a great performance booster on many parts. I´m happy to found your channel.

    • @SunnyValleyStudio
      @SunnyValleyStudio  3 ปีที่แล้ว +1

      Glad it was helpful! Next video we will talk about multi-threading to not only unblock the main thread but to perform the operation much faster:)

    • @HyBlock
      @HyBlock 3 ปีที่แล้ว +1

      @@SunnyValleyStudio Thanks bud sounds great!

  • @322ss
    @322ss 3 ปีที่แล้ว +2

    Thank you once again, neat introduction! These shorter videos are nice, it is hard to invest hours of time into long series... even if topics covered in those series were interesting.

    • @SunnyValleyStudio
      @SunnyValleyStudio  3 ปีที่แล้ว +1

      Thanks for the feedback! You might be right. I fear to become the next channel that creates "how to make box move in unity" vids or the examples will be too simple to be used in real code. Still I will try my best to learn how to make shorter videos without compromising the content!

  • @melodysprout23456
    @melodysprout23456 2 ปีที่แล้ว +1

    This is very well explained, thank you.

  • @pennaverdeful
    @pennaverdeful 2 ปีที่แล้ว +1

    Very nice explaination, thanks!

  • @vitvohralik5557
    @vitvohralik5557 ปีที่แล้ว

    Thanks a lot man! That is exactly what I was looking for.

  • @lost.250
    @lost.250 2 ปีที่แล้ว +2

    Quality tutorial, thank you :)

  • @runyu5125
    @runyu5125 2 ปีที่แล้ว

    so far the best entry tutorial about Task in Unity

  • @shavais33
    @shavais33 2 ปีที่แล้ว +5

    Wow! It looks like Unity's C# now supports the full range of C# 8 functionality! That's a *monumental* improvement over the way it was the last time I used Unity! Way To Go Unity!
    By the way, I'm very sure the poster absolutely does not mean to suggest that sweeping incredibly inefficient code under the rug by sticking it in background threads is a great and wonderful approach to resolving performance issues. Please handle async with care! It's very easy to end up loading down all the cores and make your poor user's entire system bog down to a crawl. Operating systems should probably restrict any single app from completely loading down all the cores, but by and large they don't. I'm sure this was just a rough sample to demonstrate async, but please do be aware that the machine still does actually have to run your code, and most of the time you find yourself using a nested loop like that there is probably a much more efficient way to do what you're doing.

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      Thanks for the feedback. I have actually used this in a project and everything worked well th-cam.com/play/PLcRSafycjWFceHTT-m5wU51oVlJySCJbr.html
      I still am not an expert on multithreading - I just saw than nobody mentions it and how to use it in Unity. If you know any good book about this topic let me know! I would love to improve my skills :)

  • @worldman3670
    @worldman3670 3 ปีที่แล้ว +1

    i like you! and your perfect toturial

  • @efexzium
    @efexzium 2 ปีที่แล้ว +1

    Awesome Would love to know more on how Task works with out async

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Thanks for watching! You can find UniTask which seems to be better integrated version of Tasks github.com/Cysharp/UniTask
      I will do my best to post more about the topic of multithreading 😉

  • @yuchen3587
    @yuchen3587 2 ปีที่แล้ว +1

    Simple and clear

  • @quadriproduction
    @quadriproduction 3 ปีที่แล้ว +1

    perfect tutorial..probably best explain how to use threads correctly!Thank you.Can you put the gist for this type of tutorials..would be awsome

  • @RRaiho
    @RRaiho 2 ปีที่แล้ว +1

    Holy Moly, instantly subbed to this gem channel, though which video are you referring to at the end? or isn't it out yet?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      Hey! Yeah I kind of got distracted showing how to use this in my voxel tutorial th-cam.com/video/oWFJl56IL4Y/w-d-xo.html and it took few months - long story short I forgot about part 2. Sorry about that!

  • @Ermelious
    @Ermelious 2 ปีที่แล้ว

    Is there any difference between this compared to Unity's Job System? Because both seem to be handling stuffs via multi-threads. This method I guess might be preferable to some since its leveraging on C#'s abilities instead of Unity's Job System which is still in their so called "experimental" phase.

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Hey!
      Job system forces you to design your code to be more data oriented (you have to use Native Arrays ets). When developing a game in OOP manner there and you discover a need for multithreading (you had to test your code on a single thread to know that right?) Job system kind of forces you to redesign you code.
      Async / Await also requires you to use immutable collections to output some data but they can still operate on objects so usually no code redesign is needed. On the other hand you have to manage (end) threads and handle how to cancel them.
      Jobs system is more integrated with Unity so if you know how it works you can design you code with it in mind. It should be easier to work with but you have to spend more time learning how to leverage it / how to design your code to work with it.
      This is just my opinion 🙂
      I hope it helps!

  • @ryan370
    @ryan370 2 ปีที่แล้ว +1

    This works well, but I am still stuck in my project. I can't call any unity functions without getting an error saying "[function] can only be called from the main thread". However, I need to run Unity methods asynchronously. I need to render a render texture and save it as a sprite. How can I do this without killing performance?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Hey! Things like "Instantiate() " or other native to unity methods can only be called from a main thread.
      Unity solves it by letting you call coroutine that do part of your task every frame ex create part of your map every frame (every X sec) instead of all the map immediately.
      If you have some calculations to do beforehand than it is best to run them on a separate thread.
      The solutions are - either wait for the separate thread to return you the data (how I do it using async await - you can also view section 3 of my voxel series to learn more about it) or you can create a Dispatcher that the threads will inform "please spawn object X" but its a hit more work.
      If you don't fancy doing a lot of reaserch use coroutines. Otherwise it really depends on what is your task. You may find Unity jobs to be a good solution.

  • @ikjman1
    @ikjman1 2 ปีที่แล้ว +2

    Hi! Thanks a lot for your video. I have a question about something you did not cover.
    How do I block the main thread if the task has not been completed in X time or frames?
    I'm asking this because I'm trying to make a deterministic game, and I don't want any lag spike influencing the outcome of the game. I want to use this for heavy algorithms like pathfinding long distances.
    This is how I tried to accomplish that:
    public override void Update()
    {
    SetLightSourcePositions();
    if (Time.frameCount % Constants.ShadowCalculateAfterFrames == 0)
    {
    List shadows = null;
    if (getShadowsTask != null)
    {
    if (getShadowsTask.Status == TaskStatus.Running) GameManager.Log.Error("Did not generate shadows in time.");
    shadows = getShadowsTask.GetAwaiter().GetResult();
    RenderShadows(shadows);
    }
    else if (shadows == null)
    {
    shadows = new List();
    }
    getShadowsTask = new Task(() => GetShadows(shadows, lightSources.ToArray()));
    getShadowsTask.Start();
    }
    }

    • @ikjman1
      @ikjman1 2 ปีที่แล้ว

      This results in the error being logged, but the new task being fired before the old one has finished.
      I instead want to block the main thread until the task is finished. How would you do that?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      Hey!
      I am not that experienced with multithreading but what I would do is have
      1) a thread that we run and that we have the CancalationToken reference to,
      2) coroutine that would wait for the time limit and that would stop the thread
      At the same time keep in mind that you can just use a coroutine and split your algorithm into steps / batches of data. This way you could possibly return your best estimate of the result.

  • @f11bot
    @f11bot 2 ปีที่แล้ว +4

    Does this help remove lag when instantiating large objects?
    Amazing tutorial btw!

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +3

      I don't think so. Large objects or large number of unity's that needs to move are usually split into "batches" and instantiated / moved ex 5 per frame rather than 1000 all at once. This would be a job for coroutine. Basically some operations like *Instantiate* can only be done on the main thread. Usually multithreading is all about performing calculations.
      In my Make Minecraft in unity series (th-cam.com/play/PLcRSafycjWFceHTT-m5wU51oVlJySCJbr.html) we perform calculations of parts of the procedural world using Tasks and this makes the game run smoother when moving around the map and loading new content.
      Hope it helps!

    • @f11bot
      @f11bot 2 ปีที่แล้ว +1

      @@SunnyValleyStudio Aw sad not working! But thanks for the detailed explanation, it was awesome! Gonna check the Minecraft videos to see it better in practice.

  • @Zicore47
    @Zicore47 2 ปีที่แล้ว +1

    Any Idea on how to profile tasks?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      No. Sorry. I am usually developing high-level game mechanics so profiling isn't my strongest suit.
      I will take a look at it if that is what interes you. Thanks for a suggestion! :)

  • @shubhrojyotikabiraj8322
    @shubhrojyotikabiraj8322 2 ปีที่แล้ว +1

    your complexity calculator can be used in anywhere right. To check how long it takes to execute.

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      There are many different ways to check the performance (including the profiler in Unity). What I show in the video should be reliable to use anywhere where you only deal with the code.

    • @shubhrojyotikabiraj8322
      @shubhrojyotikabiraj8322 2 ปีที่แล้ว

      @@SunnyValleyStudio alright thanks for replying 😊

  • @ShinichiKudoQatnip
    @ShinichiKudoQatnip 2 ปีที่แล้ว +1

    I cannot find the parallels follow up video 😢

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Sorry about that. The simple example did not work well with the parallel code and I haven't yet found a good example to show it. Sorry about the delay.

    • @ShinichiKudoQatnip
      @ShinichiKudoQatnip 2 ปีที่แล้ว

      @@SunnyValleyStudio oh no no, it is perfectly okay, I was just a bit too excited i guess. Take your time, will wait ☺

  • @ggwp8618
    @ggwp8618 10 หลายเดือนก่อน

    Is this going to work fine for a mobile game?

    • @SunnyValleyStudio
      @SunnyValleyStudio  10 หลายเดือนก่อน +1

      Yeah I think so. Its the C# that handles how the code runs on different devices. Worst case (ex in WebGL I think) you will experience a lag because the code runs on the main thread.

  • @mikhailnikolaev9927
    @mikhailnikolaev9927 2 ปีที่แล้ว +1

    So, why would we really need this in a game? To load some resources in the background?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Hey!
      In my 𝗛𝗼𝘄 𝘁𝗼 𝗺𝗮𝗸𝗲 𝗠𝗶𝗻𝗲𝗰𝗿𝗮𝗳𝘁 𝗶𝗻 𝘂𝗻𝗶𝘁𝘆 (about procedural voxel map generation) series I use it to generate the parts of the map that the player is getting closer to using the background thread. This was because I saw FPS drops when i did all this on the main thread.
      Generally you will not be able to use multithreading / job system unless you plan / develop your code for it. At the same time you always first create a single threaded game (with apps its easier because you know you need to fetch data from ex a server so you put it on the separate thread by default). After you know that you code is working but you can see a problem and you know it is YOU making a lot of calculation at the same time that is when you want multithreading.
      *With Unity jobs system it is a bit harder because they require you to use structs so if you don't plan for it from the start the refactoring process can take longer.

  • @ravanin
    @ravanin 3 ปีที่แล้ว +1

    Do you know of any practical examples? maybe some github project? I just don't know when I would wanna use async. Maybe just adressables.

    • @SunnyValleyStudio
      @SunnyValleyStudio  3 ปีที่แล้ว +2

      Hey! Actually generating map using perlin noise is a decent example :) any procedural Generation st runtime, saving your game data or sending data over the network will block the main thread unless we use asynchronous programming.
      If it doesn't convinces you I will use the same thing for the upcoming procedural voxel world tutorial where I create new chunk data as the player moves around the world to make it infinite. I will be starting the series this or next week :)

    • @ravanin
      @ravanin 3 ปีที่แล้ว

      It's a good example yes. but the way you're showing it, doesn't qualify as "practical" I wanna look at some proper projects not just a timer. Are you gonna use some of your previous procedural generation projects in the new series? Anyway looking forward to it. Keep up the good work!

    • @technoo4891
      @technoo4891 3 ปีที่แล้ว +1

      @@ravanin What do you mean just a timer, hejust said right now when and how to use it, on map generation or send data through internet and etc

    • @ravanin
      @ravanin 3 ปีที่แล้ว

      @@technoo4891 you sould probably google the definition of practical

  • @wisemiceclique4498
    @wisemiceclique4498 ปีที่แล้ว +2

    Async does not generally mean that it runs on a separate thread.

    • @SunnyValleyStudio
      @SunnyValleyStudio  ปีที่แล้ว

      You are right. Sorry if I made a mistake explaining it. I think Task.Run(..) make the code run on a separate thread but at the end of the day the Task class is responsible for "unblocking" the main "UI" thread whichever way is best.

  • @-Engineering01-
    @-Engineering01- 2 ปีที่แล้ว +3

    There is a missinformation here. Async methods are not multi threaded, u're on the main thread even if u use async.

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว +1

      Are you sure? Check the documentation docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=net-6.0
      "The examples show that the asynchronous task executes on a different thread than the main application thread."
      I might be wrong here (
      but if it was the same thread it could not possibly work without clogging the main thread. I guess it is really up to the Task library to schedule it.
      I have used this in a working project and there is no way all the calculations were called on the main thread. th-cam.com/play/PLcRSafycjWFceHTT-m5wU51oVlJySCJbr.html

    • @-Engineering01-
      @-Engineering01- 2 ปีที่แล้ว +1

      @@SunnyValleyStudio By using async functions, u're on the same thread but u're spliting your expensive work along the core that's why your game is not freezing at all since u split the expensive work in different timeline on the same thread.
      You can measure that using Debug.Log("This code is running on thread: " + Thread.CurrentThread.Name);
      Or you can use unity profiler to see if it's on main thread or not.

    • @endorphingames2957
      @endorphingames2957 ปีที่แล้ว +1

      Yup @Mechanics is right. Async still works on the main thread, just time slices the work to make it smoother.

    • @Izzy-fr1zu
      @Izzy-fr1zu ปีที่แล้ว

      @@SunnyValleyStudio "The examples show that the asynchronous task executes on a different thread than the main application thread." yes, but that's outside of unity. I think unity has it's own thread management that prevents tasks to run on different threads? I could be wrong though

  • @marcinziajkowski3870
    @marcinziajkowski3870 2 ปีที่แล้ว

    Why not IENUMERATOR ?

    • @SunnyValleyStudio
      @SunnyValleyStudio  2 ปีที่แล้ว

      I am pretty sure that a coroutine (if that's what you mean by Ienumerator) will freez your game when it runs when making any major calculations - ex generating procedural map in a Minecraft kind of game -> th-cam.com/video/oWFJl56IL4Y/w-d-xo.html
      Anything simple would indeed benefit from a coroutine. Anything more demanding needs async or Job system.

    • @marcinziajkowski3870
      @marcinziajkowski3870 2 ปีที่แล้ว

      @@SunnyValleyStudio So unity doesn't use multi cores?

    • @filipeduraes3525
      @filipeduraes3525 2 ปีที่แล้ว

      @@marcinziajkowski3870 coroutines still works on the main thread, so it's not really asynchronous

    • @marcinziajkowski3870
      @marcinziajkowski3870 2 ปีที่แล้ว

      @@filipeduraes3525 so if I call sleep() on main thread then Ienumerator will stop as well?
      As I understand, Await Async create new thread to execute method?

  • @SunnyValleyStudio
    @SunnyValleyStudio  2 ปีที่แล้ว

    I have used async await my *Minecraft in Unity* series to prevent FPS drops when generating additional terrain. Here is the link th-cam.com/video/oWFJl56IL4Y/w-d-xo.html

  • @okarluz
    @okarluz ปีที่แล้ว

    var x = "Guys!";
    Debug.Log($"Hello {x}");