Universally Unique Identifiers (UUID/GUID) // Game Engine series

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is jonah welcome back to my game engine series the last time we began our 2d physics journey check out that video if you haven't already it's a pretty long one but there's a lot of good content i think in there i've tried to condense it as much as possible and that's kind of the plan from here on out point is though we are on this kind of 2d physics journey and that's kind of our overall goal now to get 2d physics to the point where it like basically is fully implemented everything works all that stuff but to get there the next kind of roadblock that we have is the fact that we need to be able to hit play to play our scene and then obviously when we hit stop we wanted to kind of reset so what actually needs to happen is we need to be able to create like a runtime version of our scene that is like completely mutable meaning it's completely changeable you know there's no kind of state there that we need to worry about resetting it has to have its own separate kind of memory ultimately and state but then when we hit stop we want to kind of go back to that like editor scene right the scene that we were editing the scene like as it appears without any kind of disruptions without any runtime modifications meaning like we haven't hit play yet so there's no simulation everything is as we authored it in the editor that is kind of like that that's our next kind of step here that's our next goal because obviously since the last episode if you remember when we hit play you know everything fell and then we hit stop and then the objects remained in in that place because really by hitting play we just say physics goes starts simulating so then it changes everything and then obviously nothing kind of reverts that or resets it back to its kind of serialized state so that is basically where we are at right now that's our next kind of goal so to get there though there are a few things that need to be done now as i mentioned last time and this just is this kind of applies from here on out we are fully live streaming pretty much all of the development of this hazel 2d engine that we're working on on twitter tv slash the churno right so everything is always live streamed every single thursday there there's a link in the description so you can catch that stream and if you actually watch that vod there's actually two i streamed twice yesterday i streamed like in the morning and i just had to go and then stream later as well but the point is we got we got basically all of this working so if you want to peek ahead then feel free to actually go through that and see how it was done but what we're going to do is obviously these videos are going to kind of take everything step by step so in order to do like the play thing that i mentioned and to actually be able to like revert scenes and you know properly handle runtime scenes we actually need to implement something else and that's what today is going to be about today is going to be about universally unique identifiers or globally unique identifiers uuids goods whatever you want to call them it's finally time for us to actually implement this in our game engine because we haven't had this yet and as you'll see it's going to become a little bit of a problem when we want to kind of make sure that you know editor entities and runtime entities are kind of the same now i do want to quickly note though that if you are like if i boot up hazel here this is where we left off quick little side note as well keep in mind we are currently on the physics branch the dev branch is everything that goes on during the live stream so in other words the stuff that we've actively worked on and that i've kind of committed everything that i've done basically all the code that i wrote during that live stream yesterday has been pushed to dev but officially you know if you want to keep up with the videos these videos on youtube they're on the physics branch so just keep an eye out on that so as i was saying if we boot up hazel at the moment and we you know we hit play obviously this bounces around and we hit stop if we want to reset the scene one thing we could do as like a really easy quick fix is just load the scene again right because if you deserialize it again from disk assuming you haven't hit you know control s now actually control s doesn't even work we'll address that a little bit later we're going to have like a kind of maintenance episode where we just do a lot of you know low hanging fruit kind of easy tasks that aren't going to take us much time and aren't worth putting into a separate episode but anyway the point is as long as you don't like overwrite your save right you're saved scene if you deserialize it again of course you're going to go back to the original scene that's like a little quick fix of doing it but we don't really want to do that because obviously we might be like working and stuff like that so instead what we usually want to do and we'll talk about that more probably in the next episode is we want to actually spin off a new scene so we need the ability to copy scenes we want to have this kind of editor scene and then for runtime we need to create like a new runtime scene it's capable of doing stuff it's going to be a temporary kind of scene that we create like while our actual game is in the the play state and it basically gets deleted as soon as we hit stop right so in order to do that though um as i mentioned we need to talk about universally unique identifiers so when it comes to uuids right uh this this and that's what i kind of want to talk about today because there's a lot that you could say about it and i don't really want to go too in-depth into everything that they're used for but basically this is this is the point of them right so we need a way to identify a lot of unique objects throughout our game engine now this can refer to entities so when we create a new entity in the editor that needs to be identifiable in a unique way meaning we can't have the same name on another entity right that id has to be unique between entities now what about things like scenes scenes are also important right what if you have two scenes with the same name well again you need to be able to uniquely identify scenes what about assets how do we know which texture is which how do we know which like 3d model if this was a 3d engine is which right there's all of these different things like a sound file right anything basically that exists in the engine needs some kind of identifier so again the reason we don't usually use names for this is because it's very possible to have you know two entities that are called the same thing and and i don't really necessarily want to place that restriction that like every time you create an entity you have to make a unique name for it like that's a bit weird even if you did have the engine automate that process meaning if you tried to call something box it would call it box 2 that's still obviously just weird you just you don't want to think about that a name should not be the thing that uniquely identifies the object right assets another great example assets by file path there's a lot we'll talk more about this when we get to the asset manager asset system videos but uh we don't really want to identify assets by their file path for a number of reasons right not only because they might get packaged and zipped and compressed and the path might change entirely and we might have to be dealing with like virtual paths but also because if we update an asset or we want to move it somewhere else we want to be able to identify it in a way that doesn't concretely tie it to a specific file path because that shouldn't be the thing that you know is kind of not flexible immutable and stays the same right file paths should be flexible anyway so um that being said right instead of using all of those kind of systems like names and file parts instead we use universally unique identifiers so what they typically are right oh and the biggest question i think that a lot of people usually have is like why do we need this weird kind of uuid good system that's like you know you know if we were to like type it out you know we'd have like an id of like you know that right why does it have to be this why can't i just start started started at zero and every time i create a new entity or a new asset i increment this well you could do that right there's nothing too terrible with that in a local sense but the reason why we usually generate a random number like this is because consider this scenario right what if you are working on your scene and creating entities and then someone else on their own computer is working on the same game as you right because games aren't usually built by one person on one computer although of course they can be right what if they also create new entities well then who's handing out the ids there has to be some kind of authority like a server or something that that makes sure that you can't create you can't both create entities at the same time right because again if you're just incrementing it then locally you're gonna create five entities you'll have id five six seven eight taken up but then someone else on their computer is also going to create four entities and they're gonna occupy ideas five six seven eight and then when you go to merge the scene together nothing makes sense right even if it's in a different scene right it could be an asset that's used in both scenes well again you have the problem of if there's no authority checking this then we'll we'll have a conflict basically if we just increment now of course as i mentioned you could have a server that dishes out an id you request an id from the server and then like you know it's like okay you asked first i'll give you six and this other guy's getting seven instead to avoid conflicts we don't want to set up a server to issue ids right that does work in some scenarios and it is used in some scenarios but usually we don't want to do that instead if we generate this very random number that is at least like you know long enough right then the possibility throughout a development cycle of a game right for us for me and then the person working like behind me right to generate the same exact number it's just not gonna happen right the the possibility for a conflict is very low it's still possible right but it's very low so hopefully that kind of answers the questions of why we need uuids right we refer to them as uuids uuids and we'll we'll talk a little bit more about the implementation in a minute but uuid is good you know they basically mean the same thing and again that's why they're kind of called universally unique or globally unique because they're so unique like to the point where it's fine for you to generate one it's fine for someone else to generate one you can generate multiple at the same time they can be across different computers there doesn't have to be an authority because it's so kind of random right it's so unlikely for you to generate the same number as someone else that it's totally fine to like not necessarily use some kind of authority right and again it is basically guaranteed to in fact be a unique number so that's basically all it is right it's our quest to generate a unique number so that we can identify something inside our game engine so hopefully that kind of explanation makes sense uh and hopefully you now also see why we can't just you know increment a number like 0 1 2 3 4 and use that as as the id like and does actually entity the the kind of library that we're using for the entity component system that does have ids like zero one two three it's not really meant to be used over like multiple computers or anything but again and that's also subject to change right as in like if you uh were to recreate all the entities again you'd get different ids uh because it's it's a bit weird like it's it's not weird but it's just like it's not meant to be like an identifier for a particular entity and nc is just like an index into a set of components basically so anyway um that hopefully makes sense let's dive in and take a look at how we're going to create this by the way i want to quickly point out also that we basically have already made room for this stuff which is really nice i was very happy when i discovered this during the live stream yesterday like we already have you know u164t here uuid equals entity as uid so we're deserializing here and i think we also have um the other part of this uh i think it might be marked with like a to do yeah here it is ntid goes here and we have this like a random value here right so we've already kind of prepared it which is nice that's where we're going to store entity ids here but again this is something that's going to exist across like not just like the entity component system in parentheses and a way for us to identify entities right but it's also going to serve um you know at the asset system and like the scene system and a lot of different things basically okay so the first thing i want to do is if we pop into hazel i'm just going to mark this as like the show all files mode so that we can actually like see the folder structure because i want to make sure that i make this in the core folder i'm going to call this uid because again it is going to be something that's obviously very core to the engine and this class so namespace hazel we'll make it a class we'll call it uuid so um this uh okay so the implementation of uuid we need to talk about what it is at its core and basically in hazel what i'm gonna do is for now i'm going to make it a un-64 t and this is going to be like the actual uuid now a uuid or a good like traditionally is supposed to be a 128 bit value why that's just usually how it's defined if we want to create a 128 bit value we have a few options of course we could compose it from 264 bit values and then generate it using like a random number generator or something like that typically random number generators in the c plus standard library as far as i'm aware i only go up to 64 bits so if you generated two and combined them like you wouldn't get the best kind of behavior we'll say it's usually not the best way to do things every platform usually has a way to generate an actual uuid for you so if you actually want a 128-bit value then i think like windows has something like create good or like i don't know there's a win32 api function that will create that for you so that's one route you could absolutely take uh here on the cherno show we like to not complicate things too much and like in my experience a 64-bit random kind of uuid for the purposes of a game engine and for our purposes so far has been enough right i in in using this for like over a year and working on projects across different computers of like in using hazel 3d using the big hazel i've never had anything like close to a conflict right uh like it's just to generate two identical random 64-bit numbers that's very unlikely right it is still possible if you have millions of entities and you know tens of millions hundreds of millions of entities right um and that's why like it's important to consider the fact that if you you know uuid is if you if you picture assets if you picture entities that you create yourself well again it's not it's probably not something that you'll ever exceed right you'll probably never get to the point where it becomes likely or even slightly possible to get a collision but but um if you are if you have made an application in hazel that inside the script you know creates just millions of entities per frame right and assuming the ecs can keep up with that and everything of course you may run into a collision if pro if programmatically you're dishing out that many uuids like per second or whatever so you know i'm not going to say that it's completely nothing to worry about but for now this is how we're going to treat it now um we're going to obviously we're going to end up storing uids in maps which means we basically need to hash them so i'm going to include xhash instead of trying to include like stdint.h to get this to not be an error because we are going to have to hash them um and we'll talk about that in a minute it's obviously very easy to hash this because it's just a um 64t so how do we create them and what's the api going to be like well the way the the api is going to work is just by running the constructor it's going to automatically generate a uuid right that's kind of the way that i've designed the api so in other words if you just if you just write code such as uuid id like that it's going to give you an id right if you want 0 you can explicitly write zero for something that is deliberately marked as not initialized or something like that um so that's kind of how we're going to do it and then yeah you can take in like an id or something like that if you really want to right so this can be like your uuid uh you know copy constructors i don't even know why i kind of entertained the idea of having a copy constructor here i've got some like sample code that i read during the stream but basically if you wanted to you could make it kind of deliberately uh copy constructor but again all that's going to do is shallow copy this because that's all we really need to do to copy it so that's basically our uuid class right so how we're going to generate this random number well we're going to use c plus as random number generators right so um let's include uh uuid namespace hazel and let's take a look at this so basically i think this is all inside random i'm not 100 sure but i think it is all in here so basically if we go back and we implement like the stuff that we needed to implement the method implementations here then obviously our goal here is to just generate a uuid and then store it so how are we going to do that well we're going to use a couple of things as i mentioned from the civil c standard library we're going to mark them as static right we'll talk about this stuff in a minute but basically we're going to use something called random device and i'll explain this once i type it out then we're going to use this engine that simplest comes with which is called mt 1937 but we're gonna use the underscore 64 version because otherwise we'll get a 32-bit random value which is of course useless um to us so i wouldn't recommend 32-bit uids that actually you know having 4.4 point what is it 4.6 or 4.3 i've forgotten what's 2 to the power of 32. anyway having like 4 billion-ish um random ids is not not much uh because again it's it's not that we need four billion ids it's that we want to reduce the possibility of generating two ids that that are the same across like computers and everything right so this is gonna be um you know s uh we'll call this engine and then we're going to take an s random device with the call operator over here to initialize that again this is all going to be initialized statically i don't really need to care about this too much and then we'll use this uniform in distribution this is going to be the thing un-64t that actually distributes i'll call this s uniform distribution this is going to be the thing that actually distributes well gets us the random value so um let's talk about this a little bit well this is just the way that you generate random numbers in c plus there's not much to it if you want to dive into it a little bit more and see what's going on you can see that it's using the mercen messen mesen i don't know how to pronounce that twister engine right so that's specifically what it's doing and again you can look into it a little bit more i'm not an expert on random number generation this seems to be pretty good as in my experience and again the most important thing is that you are using the 64-bit version uh because we are we have a 64-bit good right so that's important so how do we generate a round number well it's super easy in fact we can just do it up here so we're going to set this to be s uniform distribution and then we pass in the engine right which obviously is s on the score engine and that's it so a few issues with this right um well okay there's two issues i just want to mention because i did this again on oh my computer turned on i hate it when computers turn on randomly you know it really i started like shutting the psu off on my main computer like overnight because it would just wake up sometimes anyway so excuse this guy behind me i really need to turn him off anyway whatever sorry so um again because i live stream this and i write and i plan all this code during live streams it's actually pretty good because i kind of have a list of questions that people ask that i'm going to convey to you now if you don't want to watch that whole stream but basically one of the things that people said were uh okay so what what if you did have something to prevent collision though again it's really unlikely but what if you did have something to prevent collision and someone suggested having like a hash map so having like an unordered map i mean i guess you could just have an unordered set right if you had an unordered set of uuid or un64t same thing right uh if you had an unordered set of all this of all these hashes that you want hashes but of all these ids that you gave out right can you just quickly generate it and then basically validate it to be like well if i can find that id in here then maybe try again uh i wouldn't recommend doing this there's a couple of reasons first of all it will obviously add like a little layer of complexity and some more kind of performance cost to generate uids not that we care about that too much predominantly the reason is that the reason i wouldn't do this is because uh i think the the risk of a collision is low enough that we don't need this system and furthermore clearly this is local right meaning that if someone else generates a uuid behind me again i always keep using this example but whatever if someone generates a uuid on my same project on a different computer this is gonna do nothing right so in other words like it's not really a solution um so i wouldn't like i wouldn't bother with any of that complexity right the other thing was uh threading right what about is this thread safe i don't actually know if this library itself a thread safe is thread safe you could make thread local versions of these if you wanted to the reason why i'm not bothering with that at the moment i mean first of all we don't have threads anyway here we don't like what's a thread right hazel 2 doesn't care about that at the moment yet it will move to like a render thread kind of architecture later but at the moment it doesn't so it doesn't care right but the big the bigger thing is i don't think that any other thread except for the main thread will ever be responsible for dishing out uuids right i think that's going to be only called from the main thread right and so because of that i'm not going to bother with that like the render thread is not going to be doing it it's possible that some you know if we if we offload resources like resource loading to a different thread and then maybe the asset manager has a generate uid it's possible that it does that through the resource thread or some kind of job thread right in that case we will need to think about it but yeah anyway welcome to the game engine series the show where we write five lines of code and then talk about everything possibly that can happen in the future right ridiculous anyway whatever i mean i'm happy with this guys so just let me know let me know what you think because i this series like i don't know i've given up on this series i've give i've given up on this series in the sense that i like it is just going to be as complex as it gets it's going to be as these episodes are going to be as long as they get i don't care right it's just i my job is to kind of give you guys as much information you guys seem to enjoy me talking about what's in my head and explaining it to you so that's just where we are okay now next step is again as i mentioned it'd be nice to use these uuids in like unordered maps uh and in unordered sets right so in other words we need a hash function to be able to hash this now guess what this a uuid what is it it's literally 64 bits and it's an integer right very hashable c plus doesn't know that though so what we have to do is actually provide a hash function now it's very easy to provide a hash function and again if you're still a little bit confused as to why we even need this then uh let's i'll show you why right um this might be a little soil on how to write a hash uh function as well another map is probably something that you're more familiar with than on another set but if we have a static void add to map let's just say we have a std i've got a habit of running of writing static everywhere because i don't like variables to be global but under the map um uuid i don't know entity or something we'll just say string uh map right this is not gonna work right we're not gonna be able to say like make me a uuid and then assign it to cherno right that's not gonna work why because there's no hash function for this right um well why is uid undefined though you for real asks this in hazel lol okay i don't know why i did this outside of the hazelnut space but whatever right that's not gonna work um it might say that it does uh but when we actually try and compile it no i didn't include the pch i don't know why it says that it does though it's going to tell us that and this is a very common error that i get a lot of messages about attempting to reference a deleted function and i mean ultimately it just can't hash it right and if you if you look at it um the the point being that ha like it's gonna work fine if we just treat this as a un-64 t right and it's totally reasonable to do that because uh what what we might do is we might make this castable let's make that happen real quick so since the uuid is just a un64t what we can actually do is create an operator that will actually allow us to cast that so i think it's like operator i don't think we need constant or anything unct 4t const return muuid right so this will let us basically have a have an op it basically tells us that if we want to treat this class as a uuid so if we want to cast it or even implicitly cast it it's going to return uuid right because again it's just a wrap up for this one integer it's important to understand in c plus and then see that like classes trucks well more important than c plus plus possibly because there's a lot more to classes potentially but classes in c plus plus they are just the members right again if it's if you have a v table et cetera it's different but they're just members right at the end of the day this is what the class is and these functions are just like stored in other space in the binary right so point being that we can obviously kind of treat them as their type in this case if it's just a thin wrapper like this so by doing this we've kind of solved the hashing problem this will work right why it's turning into a c plus tutorial anyway why because you know we can cast this to a unc4t and everything's great but that's like slightly annoying right i want to be able to do that right so how do i do that well again what you need to do is just provide unordered map with a function it can use to hash this because if it's a key it doesn't know what a uuid is just some custom class right i missed this again right it doesn't know what it is so how is it supposed to hash it so that the unordered map works properly same thing with if we just use a map right instead of an unordered map we would need to implement like the less than operator so that it could actually put it into the right spot in our tree um so because of that uh we need to define this kind of hash function that's going to be used so how do we do that well i'm not going to pretend to remember how to do this because i always have to look this up but basically we can just do you have to do this in this in the std namespace we can just type instruct hash um hazel uuid right and i'll explain this in a minute so we're creating a we're creating a template specialization of a struct right and a structure is the same as a class right but this is a specialization so the hash is kind of a temple oh go away the hash is a kind of you know hash has a template it's like a template class defined like this but this is us specializing it just like we would with the template specialization we've done template specializations before because we have this annoying pile of trash over here right i still during live streams recently i was like why did i add this this seems like such garbage but anyway whatever we'll get back to that on a different day um so anyway point being that over here with the with with this hash it's just this is just our template specialization we're providing it with a way to do this and so for that to work again this is not my code it's c plus plus a standard library code i'm just writing a specialization for their function we have to implement this kind of call operator which is just the kind of parentheses operator right so that when we call hash on this type right when we try and hash this type it's going to return a size t and that's going to be our hash right and so what we could do is again if this was a little bit more complicated like uuid wasn't just a 64-bit thing then we would just get it to generate one for us right and again this i think this has to be a const reference just because again this is their function um so and then what we could do is now we just return our hashing code so how do you want to create the hash how do you want how do you want me to hash this value when you pass in a uuid as a key into another map for example right and again because like a uuid is just a 64 bit value we don't need to hash it ourselves the c plus plus library provides a hash function for the 64-bit integer type right and so because of that we can just run hash but we can basically just redirect it to another specialization of this hash class and that's going to be this and then again how do we get the hash from there we just do you and 64t uuint 604t uuid and that's it right that uh should basically be it oh except we have to call this right and then that's the parameter okay so again we're using the call operator to call this same function but for un64t and that's where we're redirecting this to so that's how we write a hash function again you just need to create a specialization of this and this for your particular type and then do whatever code you want to generate a hash for it a little bit confusing uh but this is going to be a good reference point for this i don't think we've done this in the past maybe we have and this has been a waste of time but anyway that's it right that is how we that that's how uuids work and how um we can basically use them like and how we can hash them and how we generate them and hopefully everything you need to know about uuids okay cool so how do we use them now in the engine well what i'm going to do is basically make room for uids inside entity right so the idea is and what we're going to use it for initially is when i create an entity i want to give it a handle right like i want to give it this uuid as a unique identifier as a globally unique identifier for our entity right so how do i do that well we basically need a way to obviously store it on the entity how do we store things in the entity as a component right so we use an ecs which means that it has to become a component i'm going to do it as the very first component here i'm going to call it id component and then we're going to give it a uuid and i'll just call it id right and then i'll copy the same pattern that we've had over here where we basically have the copy constructor and a default constructor right now we need to include uid um by the way a quick thing about includes i don't like like um i should probably establish some kind of uh policy slash style guide here but usually i like to include our code first the reason being that well first of all you should define some kind of order so that it's not just intertwined right but the reason why i like our code first is just in case there's some kind of configuration files that might have like macro definitions or you know stuff like that right defines in them whatever so that way we can just kind of make sure that they're actually compiled first right and then we include the rest of this code so that this code might be affected by that code if that makes sense unless there's like a reason why we can't do that anyway so that's how we create an id component right we can now have that so it's really important now that every time we want to create an entity we give it a uuid so how do we do that well we have a create entity function right it has a transform component all i'm going to do is also get it to add an id component now that's actually that's it that's all we have to do right because by adding an id component it's going to call the constructor that's that itself is going to generate a uuid for us immediately now we'll also need a function called create entity with uuid um and the reason that's going to need to happen is i'll show you in a minute right is because of the basically deserializing entities if we want to create entities in the scene that have already been created like because they're just being deserialized or there's plenty of other reasons we obviously need to give it a uuid that we will for example read in from the actual end from the actual like deserialization from the actual kind of yaml file that stores stores all of our scene data so let's serialize it first though how do we serialize an entity well um yeah i'm just thinking about this no maybe let's oh yeah let's make civilization work because what i'm going to do is i'm going to deserialize it get hazel to generate uuids for all the entities in our scene just randomly because we're not using them anyway yet and then serialize it again the reason being that i don't want it to deserialize this number and then put that in that's going to be a bit weird so if we want to um get a serialization working then instead of just using this i just want to be able to basically ask the entity hey what's your what's your id right and we can probably just assert here that if the entity if entity has component uid like if that's not the case if it doesn't have that uh sorry i you id id component if it doesn't have an id component then we don't want to serialize it like it's probably an error because we're probably trying to serialize some kind of like scene meta entity or something weird right every entity has to have an id component um so uh okay so how do we get it well again you could do entity get component you uh what is it id component this is just so annoying though right getting getting energy's uid such a trivial task i want to be able to actually just call get uuid and then that's going to look up the energy component system so again we're using this kind of entity we're using this kind of like entity class as just a wrap up for us right to a wrapper that will do all of the ecs stuff for us that will just make our code a little bit simpler so how do we add that well actually this turned out to be a little bit confusing during the live stream because we actually include scene here um and that led to some problems and i'll show you why in a minute um hopefully it will i mean it should it still should lead to problems here anyways the point is if i want to write a function called get id right then what's what's this going to be it's going to be get component again we could do it like an assert for house component but um whatever so get component id component dot id right that's what it's going to return this gives us an error right why does this give us give us an error because uh apparently no um i just i'm just going to make sure that i did it correctly i think i did anyway point being that i think um but we're including scene aren't we so actually this probably should work uh [Music] no function template i get get component id component ah sorry that's because i marked this as cons for some reason yeah it seems to work get you id unknown syntax error oh uuid okay well yeah that's that's fine that we can include uid ui doesn't it doesn't include anything so we can definitely do that i wonder what was up during the live stream because i feel like either we didn't have the scene include or yeah this looks uh here we go id oh this is the problem sorry i knew there was a problem so basically we have to include components so that we can access specific components like id component but unfortunately components includes scriptable entity which includes entity so this becomes a bit of a recursive include components include entity entity includes components and obviously if we try and like control f7 this it's not gonna work right so how do we fix it well we basically uh look at like components shouldn't be including entity right a component a component generally doesn't know about entities however you can see a scriptable entity is the culprit because scriptable entity includes entity so what i'm going to do is not include scriptable entity here right we use it over here but what i'm going to do is i'm just going to you i'm just going to make a forward declaration for it because you can see the scriptable entity is just a pointer anyway so we can just define it like this right and then actually include the scriptable entity class when that pointer needs to be used right so i'll just do a little forward declaration here and i think if we hit compile now it should work and then i think in scene it probably won't work because it doesn't know what it is but this is where we include it right so include scriptable entity and then it should be okay we get a static assertion failed because we need to add this pile of garbage um i'm gonna really really rethink this system this was just a way for me to basically have a non-component added function i don't know why it has to be present though but whatever well i guess i guess we could have just removed the static assert and it would have just used this and not done anything actually why why why why was the static or so false what why can't we just do that because clearly it's going to use this if it can but everything else doesn't need to exist anymore right wouldn't this make more sense and still work yes i don't know man i don't know what what past me was thinking again maybe someone who has actually gone through that episode more recently knows why but whatever all right so where are we now um so now what should happen obviously is the scene serializer should serialize the correct uuid and we should in fact have a different uuid for everything now so if we actually go to um hazelnut into assets scenes and into physics 2d let's say you can see we have the same uid everywhere what i'm going to do now is launch hazel it should generate uuids for us right immediately when it deserializes these entities if we can even get the thing building okay well this is upset now so maybe that was i should have probably tried linking it not just bit not just compiling it um [Music] on component added but why doesn't it just call the oh because the template wasn't defined in the header file that's why so it actually needs it because this we decided not to define because i don't think we could define specializations just in cpp files and we probably didn't want okay yeah this is this is annoying okay we'll keep it we'll keep it for now but this entire system i will rewrite later yeah so in case you didn't follow along the reason that i didn't link is because this isn't defined here so it actually needs a concrete definition for every type it can't generate a template in the other hazelnut module which is the exe file okay so if we um try and load this right if we have a quick look at this so these are the uuids right but if i save it now if i overwrite this so assets in physics 2d so if i override it like this yes then you can see now right every one of these is obviously different it's unique right so i just go ahead and quickly do this with all the other scenes okay so i've done it to all of the um different scenes now they all should have uuids and now they have uids let's actually not regenerate them every time right because obviously if we run it again what's going to happen is when we deserialize an entity inside the serialize so let's find the other to do it's just still going to call msn create entity what does that do it generates a new uuid so we obviously need to make sure that we're actually creating it with with the uuid create entity with uuid and so we'll type in taking a uuid just by values fine it's just a 64-bit value create implementation um and then we're basically going to do this right it's just that this uuid when we add component you when we add this component right it's going to be specifically this that we add right uh let's just make sure that this uh should be fine right error type okay arrow type what uuid is an error type okay let's include uuid keep it in alphabetical order okay should be good right and then so we'll just change this to be return create entity with uuid and this is going to be you so we'll generate a uid in this case and then we'll pass the name through as well okay so now we're creating it with a specific uuid uh and that's it then we just change this to create entity with uuid and obviously we don't really have a way of verifying this but it should actually not create um you know a different one so we'll just pass it the uuid that it has retrieved from this yaml file right so now we are properly serializing and storing our uuids that we generate okay that's it so i'm going to remove these two do's um and i think we're pretty much good to go i guess we'll validate this so the way we'll validate it quickly is we'll just make sure the camera is always is 47939 like blah blah again right we could serialize this as um [Music] hexadecimal i guess to maybe save some bytes of text i don't know i don't really care i don't know i never i never seem to care about anything but i just don't care at the moment okay so physics 2d that's what we were looking at right so if we save that and we actually override it again right i'm hoping that we have the same one so it changed position which is fine but you can see camera is four seven nine three nine right so it has in fact remain the same see that's also why we don't trust and or entity for any kind of id stuff it's not built for that it doesn't guarantee that it can change stuff all the time and that's totally fine that's actually totally fine we don't care because we have our own id system as we should for something like this okay so now every entity that we create is going to have its own generated uuid which we should probably display here somewhere in hazel in proper hazel we if you hover your mouse over the tag it actually pops up just in case you want to debug it or whatever but usually that's not really required anyway i hope you guys enjoyed this video if you did please don't forget to hit the like button patreon.com i'm forever grateful for all of your lovely support uh you'll get access of course if you support there to the big version of hazel and see all of these concepts already implemented and your support is what get what keeps this series going as well now that we have laid down this groundwork next time we are going to jump in and make it so that when we hit play and stop it actually reverse our scene properly we'll set up all of that runtime scene functionality uh i'm not going to make you guys wait a week because next thursday actually is when we are going to keep live streaming and keep working on hazel so i'll probably just make another video throughout the week right so expect another one in a couple days or three days or something like that and we should be able to get back on track thank you guys for watching have a great rest of your day goodbye [Music] you
Info
Channel: The Cherno
Views: 26,746
Rating: 4.9248657 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, game engine, how to make a game engine, game engine series, uuid, guid, universally unique identifier, globally unique identifer, ids, id, game engine ids, game engine uuid
Id: O_0nUE4S8T8
Channel Id: undefined
Length: 41min 38sec (2498 seconds)
Published: Fri Sep 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.