Understanding the WorldSubsystem in Unreal Engine

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I just spent the last 5 days over 30 hours refactoring my path finding grid code from everything being in one actor to 12 different FS separated by Logic connected by this world subsystem and in this video I wanted to share with you guys what I learned in this video I want to go into the details so what should you learn in this video the first thing is uh the details of the life cycle of the world subsystems the second thing is how you can use the world uh settings with your subsystem to configure the subsystem how to override the functions in the subsystem instead of things like uh delicate world events and how you can access the subsystem in your internal code using the outer with an interface so yeah subsystems are pretty great and the world subsystem is meaning that some code is binded to the world and a world how I see it is like the level and the map so when you change a map the world will change and then the code related to this subsystem will de initialize and will initialize again for a new world and for git this makes sense because the world is has a specific grid and we want to load the grid for each world and the cool thing about these subsystems is that you can access the data from anywhere in your code also bind to it uh with event so if an event is thrown in the subsystem you can sort of bind to it through your blueprints or C++ code so it's just a very cool tool it works similar to a Singleton that means it will be initialized once and then never again so yeah I I really like the concept of subsystems turns out you can actually clean your code up quite a bit and encapsulate it a little bit so it's a contained so one thing you might notice when you're debugging these subsystems is that um the code is triggered when you compile the project at around 90% I think or 75 it triggers this initialized code so that's a bit strange because compiling the code um you would not expect this initialized function to trigger but it happens uh and to test it out I put a random number in the subsystem and this was actually quite useful to determine what system is being triggered for what code what you see here it initializes the uh the subsystem but also immediately de initialize the same subsystem uh for the compiler so that's the one we can sort of ignore and then when it loads the editor it will also create one 727 but this one it will not the in initialize so only when we close the editor it will call this the initialize um function so the subsystem is staying alive until you close the editor so it will not only de initialize when you um uh close the editor but will also de de initialize when you change the map because it will de initialize it this was a new one the old one but it will initialize a new one and this is all still in the editor but similar things happen when you uh when you play the game in game so when you change a map it will de initialize and will initialize the new one let's go back to our original map it will de initialize this one it will initialize a new one we're still in the editor but now when I click the play in editor button we'll see it initializes a new one but it still has the editor uh subsystem as well in the backr this is something good to know because sometimes when you use events um you will get like different subsystems are calling events so the editor subsystem is still running but also the game subsystem and when I close the game it will de initialize the game subsystem so that's good to know so I used to use the actor to set like settings for the grid for example U the grid block height the cell height the width how many grip blocks we need and how many cells Etc which one should be unlocked um and they used to be in the actor but now I moved them to the world settings this is nice because every map will have a world settings I still need the actor to be able to drag around uh static meshes so they should be attached to an actor you cannot actually um use the world settings for that and so there's still some use for actors but everything related to the grid that I can configure I can configure in the world settings now that works is quite easy you can just create your own New World settings the best way to do it is just use the editor at new C++ class search for World settings and you get like a new uh World settings class that looks similar to this one it will overwrite the world settings and then you can just add your own data make sure you use a property uh with the correct values and there's one cool thing you can also do with these World settings and that is to calculate a few things so I have a few things I want to calculate like some offsets and the total height and width and I can do that by uh doing these post edit changes and also uh on the Constructor I'll calculate these values uh and I set them to these properties and then I will have access to them not only in the editor I can see them but also in the goat and this is important because the world setting is like the place um where I calculate things but I put them here instead of the grid subsystem because I also want to show it uh to the designer that uses the editor these could be handy settings to see so we have the world settings and how can we Implement them in the subsystem you can just use the uh the world to get the world settings in the initialize code and this should always be set if uh if it's set and then you can uh use it in the rest of your code so I'm not actually storing it in the in the uh subsystem but I am using it to initialize some classes in the subsystem you can actually bind the world delicates so the world events a to code in your subsystem that's how I initially did this um but the issue here is that if if you have two sip systems running for example when you play an editor you can get some strange bgs where um the game world is being thrown to like the editor subsystem and then it runs some code and we got some strange bugs because of this um but you can do it but if you do it it's good to test that you could be in the editor world so one thing to test is to uh check what world it is is it the game world versus the editor world and on most cases you probably want the game world but you most likely won't need these function so to initialize to understand you cannot do everything in there it's being called very early in the in the world building process I'm not sure how to call that um but one thing you don't have in the initialized function is the actor the actors and the actor locations so how to do this I would wait for the actors to spawn with these events then I would have them but you can actually use the native functions in the world subsystem so there's these functions on world uh begin play on components update and on post initialize and the and the order matters to these functions so the order is that we first initialize the world then we post initialize then the world components are updated and here we actually have the uh locations of the actor so in my uh place for the grid code I had to do a lot of code here instead of like the initialize and then it uh has to begin play I actually don't need to do anything there yet and then the de initialize when you close the subsystem so it's better in general to use these functions when you can instead of uh using these events and if you use the events make sure you have some check if it's the game world or the editor world to prevent bugs so you might want to have also have the tick function of the world available in the subsystem and for that it's best to instead of using the world subsystem to use the uable world subsystem you have to override two functions to get this to work the tick that the function that you want but also this get stat ID um and you have to implement it like this that you uh use this weird delicate thingy return quick declare cycle stat with the name of your subsystem and then this stat group tibles and then you would see the tick tick tick tick so when we have the subsystem we can easily call it anywhere in our code like this get World get subsystem and then the class of our subsystem and then we can use all the functions all the classes attached to it so it works great but what if you want to run some code or get some um data out of the grid subsystem from your internal code that's actually used in the subsystem so there is an issue and one is that the subsystem is using like all these things the map crit actor the grip block the grip block settings everything that we need the grid Helper but let's say we want want to get uh the Grid in one of these functions then we had to do a lot of weird things and we had actually had a big issue where we have these widgets they are being initialized and it was very difficult to put this data like the cells from a function to another function um so there is a way out of this and it's actually pretty cool so here we have U the the way we initialize uh these U objects you can set it do it like this new object is the U grid helper with this and this is the outer of the grid helper so we are if we are in the grid helper we are the outer so it's sort of the owner of and you can only do this with u objects but everything we need is U object almost um so that's fine um but still we cannot not access the um the U grid system class because we would get a circular reference like we use the helper here include Helper and that means in the helper that we cannot include the subsystem so to get around this you already see this there's this grid subsystem interface and there we can make an interface just a normal one going to the tools new class interface and here we can get some data out by using these functions so these are like a virtual functions con means uh we should not change the the array um so the is n makes this an abstract class and the con is sort of saying to the um to the code that implements this that you cannot change it you just uh should not change the array so it's a bit a way to Signal what you can do or should do with it so we implement the interface in the U grid system by using this public interface after the uh World System interface and then we have to implement these functions the get cell the get grid blocks and the get grid nodes and then in the helper what we have to do um so here we have code where we actually want to get uh some grip blocks and we can use this outer to get the outer then cast it to this interface and then we'll be able to get the grip blocks out of the grid system so this is a handy way you can also use your grid system inside the code that is sort of part of this whole encapsulated grid logic if you like the video please share subscribe like like follow on Twitch um it will really help me make more of these videos thank you have a good day
Info
Channel: SeriousPapa
Views: 236
Rating: undefined out of 5
Keywords:
Id: Dt3XH-nX5Ps
Channel Id: undefined
Length: 14min 8sec (848 seconds)
Published: Thu Jan 04 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.