Async Code in Unreal Engine: Multithreading, Runnables, & Promises | Indie To Indie

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
and welcome to the first episode of a new sporadic series that I'll be adding to every now and then I know I said last time that I was taking three weeks off but I hope that this is a short video to produce and I'll be able to crank it out in a few days I often include little amuse Bouche pieces of advice that I stumble upon in my devlogs and I think it'd be worth branching that off into its own series hell it would make my own life a lot easier so I could reference them more quickly instead of having to look through all of my scripts so this series is going to be exactly that this is episode 1 of Indie to Indy the series in which I'll go through some practical advice for gamedev that I've discovered well doing Game Dev myself this is going to be an on and off series that I'll add to in between my devlogs anyways this pilot episode is going to be one for the programmers truly asynchronous C plus plus in Unreal Engine I recently fetched about the quality of unreal engines asynchronous documentation so now I'm going to give you all a couple Helping Hands so you don't have to repeat the same slog that I did asynchronous code is sort of like quaternions most of the time you don't need to know them but when you do you really do let's keep one thing in mind we're game devs so that means we have to keep frame rate high enough to be playable and more importantly enjoyable so if you ever have code that is very computationally heavy custom pathfinding in my case asynchronous code allows you to run all that stuff on a different thread so that way your game's frame rate doesn't tank this video applies to both ue4 and 5 but I don't have Unreal Engine 5 installed so I'm sticking with ue4 I've created a demo project to go over a basic example of how to write asynchronous C plus plus that I will iterate upon by adding more robust behavior and functionality and I do mean C plus plus but you can set timers in blueprints you cannot node your way to truly asynchronous code and since this is a pro programming episode I'm going to upload the project with the code to a GitHub repo check the description for the link asynchronous code and multi-threading is basically diving straight into the deep end for programming so if you're unfamiliar with C plus plus you might want to tap the bricks as I said just like with quaternions you can get around a lack of technical knowledge with creativity and elbow grease so with that disclaimer out of the way let's get down to the good stuff the easiest AKA best for Indies way to write asynchronous code in Unreal Engine is to use the F rentable class and if we look at the docs we can see they're very good so I've already written all the example code step by step and the first step is this just a class that prints out step one this code is running asynchronously every one second as you can see this step one class is a subclass of f rentable and I've overridden the virtual functions init run stop and exit in order to set up my asynchron functionality along with a Constructor and Destructor as you can probably guess F platform process sleep is used to sleep this thread in effect making it wait for any amount of time you can use this to quote unquote slow down code if it is still hugging too much processor time and if you take a look in the Constructor you can see that I create the actual thread that will be run asynchronously there you can create this later in order to delay the asynchronous code running and as you can probably guess by the name init init just initializes things I have the returning true to launch or false to not and stop gets called when the thread itself is killed next I needed a way to actually start running this runnable from the main thread so I created a nice little actor class that I'll be using throughout this walkthrough I have functions that I exposed to blueprints for each step and I created a blueprint actor that is a subclass of this actor so I'll just be launching my example code from the Again Play node important to note is that I overload this actor's on Destroy so that way I can delete the F rentable for each step of this video so let's give Step 1 a whirl and yep it works however when I stop it we see one problem it keeps running even after the actor is fully destroyed this is a memory leak and it is not good enough memory leaks and you will tank the frame rate exactly the opposite of what we want now why is this happening even though we set up a Destructor and everything since run never stops thread kill will never actually kill the thread since run doesn't stop to check if it should stop so we'll move on to step two how to prevent that while also adding a bit more functionality this new runnable will only run for a given number of times and then it will stop plus when I delete it in my actor it will actually stop as you can see I'm using the variable B stop as a flag to actually stop run if it needs to be stopped early now when I create the thread in my actor class I just pass in the number of times I want it to run as an argument to the Constructor and if I stop the game it cleans itself up nicely now for my complaints run should only be used to return the exit code of the runnable object zero means execution ran fully and anything else should correspond to a different reason why execution ended quote unquote improperly if I wanted to do something a little more complicated than that we're going to have to look beyond what we have right now and this is where promises come in let's say I wanted to do some real hard math on my new thread getting a list of all prime numbers from 2 through 10 million your first instinct as a programmer may be to just pass an array of ins by a reference but bear in mind we are working asynchronously I do not know when run will end so if I use that array before run finishes I I won't get what I expect maybe if you've done a bit of multi-threading before you're thinking callbacks listen I've seen how messy nested callbacks can get and I've written more than my fair share so I will not be using those instead I use promises what's a promise promises or Futures are programming patterns that lets you do something with the result of either regular or asynchronous code once it's ready hence the name promises are not the result itself but a promise that it will turn up eventually if you're familiar with JavaScript you've probably used promises before and really like them I rarely praise JavaScript but promises are so nice in it but unfortunately while Unreal Engine does provide them they're not as nice as in JavaScript so unless you want to program something better yourself the out of the box stuff is all we got so how does a promise work well just like with my f rentable examples I've set up examples to show you here's a basic version as you can see we get the the future that the promise promises then we can add a function that will run immediately after the promise resolves to a value this function is called a continuation and when I hook up and run this basic example 4 is printed just as expected important to note with promises is that if you set the value more than once you'll get a game crashing bug which is really bad for the frame rate the advantage of promises over callbacks is that I can chain these continuations without nesting them so everything stays more easily readable but again not as nice as JavaScript and for this example it's important to note that even though I said the value of Promise B before promise a the result of Promise a is still printed before promise B's result so chained promises are good to use when you are waiting for the result of more than one asynchronous thingy or want execution to happen a fixed way regardless of resolution order so for step 3 of the F rentable example here's that prime number Bad Boy featuring promises as you can see at step 3 I am now deleting the promise in the exit function since this function gets called after the thread fully finishes after that I just had to write a few more lines in my actor class to take advantage of promises you could try deleting the promise in the continuation instead of in the exit function like we did in the chained promises example but it'll cause some bugs so don't so when I run it I have to wait a little bit but ultimately it works then if I stop the game before it finishes it cleans itself up nicely and if we look at the FPS hey if it's good in the editor it's better in game now this brings us to a design decision I'm setting the promise value to an empty list if I stop the F roundabout early now to me this is inappropriate I'd much rather resolve to a different value specifying why execution stopped so I created a wrapper to add that behavior on top of the resolution value it's a lot easier than you'd think I just hammered up the following lines as you can see it's super simple now I can set the promises value to different resolution types to specify why execution ended and since it's an enum you could of course add more resolution types and now the continuation function can have different Behavior based on why the asynchronous code stopped for this video I kept it simple but you should get creative and do whatever you you want and when I run it after waiting a bit it works just as expected and if I stop it early it says so and as a final piece of advice if your code is crashing you might have to add a minuscule sleep before setting the value of the promise asynchronous code is weird like that I like to add a preprocessor directive so that way I can easily toggle it on or off if I need to and that ought to do it for you keep in mind you can add extra methods to your F rentable subclass as needed after all it's your code base for your game make it work for you and that's it for this pilot episode of the new indie to Indie series let me know what you think as I said at the start you can get the project with code from the GitHub repo Linked In the description so help yourself as I said this will be a series that I dip into now and then so don't expect back-to-back releases like with the math series editing update there's also a Discord server and you know it's pretty chill I like it so come on by say hi there's a Game Dev channel art Channel cooking baking Channel and of course a math Channel where I and hopefully some other people will start Fielding math questions but you know having fun so far so come on by say hi make yourself welcome and as always thank you for watching I appreciate your time and I hope you have a good day if you liked the video please give it a like and if you want to follow along with this new series my devlogs or the now largely finished Game Dev math series Please Subscribe I release new videos every two weeks sometimes even when I said I was going to take a week off and your comments are all wonderful I read all of them and try my best to respond well keep it up I'm also on Twitter where I definitely Post in order to vent about creating 30 plus long minute videos I also post what I bake when I bake it so to see things fresh out of the oven instead of waiting for the fortnightly baking segment give me a follow there and speaking of bacon segment I missed it and I hope you did too let's get to it and this baking segment is gonna be a double feature since I only took a single photo of both of the things I baked for this segment so first one is a another Apple galette again I really like this recipe however um I keep on having trouble with the compote I think you know every time I've made a compote it uh the crust you know pops so but again uh I used oh this compote was really good though so it was definitely worth worth the burst crust uh I made it with apple Calvados and oh it was really great I really I had a slice of this with some friends and I really enjoyed it so this was a good one and as you can see there's a bit of an egg wash on the crust so this one came out really good I was happy with it well it came out good aside from the burst part but yeah that Apple compote um well my rule of thumb is whenever you're cooking with alcohol it was gotta try it a bit a bit maybe a more just gotta make sure it's still good still fresh you don't want to be cooking with bad ingredients after all so this was great and of course I mean that pie crust recipe it's amazing easy quick love it absolutely love it and next we have something I've never done before on this channel um so over the Christmas one of my gifts I got a pizza steel so I've started baking pizzas now and uh this is this is basically my training Arc is coming up for pizzas soon so this is the first pizza that I baked that wasn't a calzone the first one was actually a calzone and I was too distraught to take a picture but this was the first pizza technically and as you can see it I mean it came came out pretty good uh again this is I'm trying to do a since it is a pizza steel I tried to do a Neapolitan style pizza and you know day two I'm still dialing it in uh if you stick with the arc which is when I just baked a pizza every night for a week including the calzone by the end of the arc I was I was nailing it the crust was super thin so this is basically day two still don't know what I'm doing uh there's some hot honey on it which I really like hot honey it's a good ingredient made everything by hand everything by scratch tomato sauce dough well not the cheese I guess but you know it is what it is uh I'm using apparently you're supposed to use uh if you're making like a New York style Neapolitan of course you just fresh mozzarella this is a high excuse me uh high fat low moisture mozzarella so it's not fresh mozzarella which I use later on in the arc but this one came out you know I liked the calzone too the calzone was also tasty despite it not being a pizza I really enjoyed it but this was good too so I was really pleased with how this first successful pizza attempt came out and when like we continue going through the pizza Arc you'll see that I improve pretty quickly and the pizzas get better and better so that's it for this episode and you know Pizza That Dope it I did use my sourdough yeast my sourdough starters so I am I can say this without fear the yeast in the air is free I go out there and bake it's delicious it's good for you and it makes a great gift and it's an easy way to show your appreciation to the people you truly care about and I care about all of you thank you and I will see you next time
Info
Channel: Natsu Games
Views: 4,426
Rating: undefined out of 5
Keywords: ue4, ue5, FRunnable, multithreading, C++, async, asynchronous, promises, madewithunreal, programming, tutorial, indie, indiedev, gamedev, game development, indie dev, code, unreal engine 4, unreal engine 5, Runnable, future, futures, promise, video game, video games, vidya
Id: UyloKYQpYFM
Channel Id: undefined
Length: 15min 18sec (918 seconds)
Published: Fri Apr 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.