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

Поділитися
Вставка
  • Опубліковано 30 тра 2024
  • Patreon ► / thecherno
    Live Stream ► / thecherno
    Instagram ► / thecherno
    Twitter ► / thecherno
    Discord ► / discord
    Code ► github.com/TheCherno/Hazel
    Series Playlist ► thecherno.com/engine
    Chapters
    ---------------
    0:00 Intro and The Plan
    4:25 What are UUIDs and Why
    10:30 UUID Implementation
    21:46 UUID Hashing
    28:25 Using UUIDs in Hazel
    #Hazel

КОМЕНТАРІ • 109

  • @lamofabull7844
    @lamofabull7844 2 роки тому +49

    Hey Cherno, thank you for continuing this series for so long. I’ve learned a ton from it and it’s motivated me a lot to branch out and try things like vulkan and directx programming (tho it makes using typical game engines feel boring lol)

  • @movingheadmau8128
    @movingheadmau8128 2 роки тому +7

    Thanks a lot for making this content. I am not actually making a game engine nor do I plan on doing so, but just watching these videos and understanding how the behind the scenes stuff works is amazing. Also, it makes me ever so more grateful for what engines like unity provide out of the box and also for free.

  • @gebriish
    @gebriish 2 роки тому +13

    Congrats on 400k subs man , all the best for the coming days !

  • @ModerateDev
    @ModerateDev 2 роки тому +1

    The way you navigate around your code is mesmerizing so fast and with such purpose, incredible. Great video keep up the good work!

  • @theRPGmaster
    @theRPGmaster 2 роки тому +13

    I love the in-depth talks and future proofing, more of that please. It's all surprisingly relevant! Keep the great videos coming!

  • @guysgaylord3620
    @guysgaylord3620 2 роки тому +46

    Still waiting for ur Assembly series. It was like a promise from 4 years ago

    • @mr.mirror1213
      @mr.mirror1213 2 роки тому +2

      Sheesh would love it

    • @oguzhantopaloglu9442
      @oguzhantopaloglu9442 2 роки тому +1

      Yes that would be amazing!

    • @redd_cat
      @redd_cat 2 роки тому +2

      In 4 years you could of learnt it from elsewhere and become very good at it. Why wait for him to cover it before messing around with it yourself?

    • @guysgaylord3620
      @guysgaylord3620 2 роки тому +1

      @@redd_cat I started learning 6 months ago. I know it's a promise from 4 years ago because he had mentioned it in an old video I watched yesterday and I just want to know if he can make a series of it or not

    • @Futureblur
      @Futureblur 2 роки тому +1

      Hey what's up guys, my name is the Cherno and welcome to another episode of the Assembly Game Engine series

  • @ambid1795
    @ambid1795 2 роки тому

    This was perfect, and came out just in time! Thank you!

  • @DerrickCanfield
    @DerrickCanfield 2 роки тому +8

    I just added UUID logic in my engine this week. I've been patching up the engine and I had been using Boost for UUIDs among other things, and I finally ripped it all out in favor of my own UUID class. Since all of my serialized data is the standard 128 bit UUID format, it made sense for me to keep the same 128 bit identifiers to avoid breaking the existing content. I like the idea of only using 64 bit UUIDs since it doesn't really need to be larger for that for most engines.
    As far as validating for UUID collisions, I believe Unity does when importing an asset or possibly even only when first opening the project since I have seen the warnings appear for UUID collisions. Unity then issues a new UUID for the second asset in the collision. You could do that in Hazel, but it's likely overkill for an issue that hopefully rarely crops up.

  • @jimbo3947
    @jimbo3947 2 роки тому +2

    You literally read my mind, thank you for this.

  • @icaroamorim3123
    @icaroamorim3123 Рік тому

    This is very very good material and the code is really easy to follow along

  • @rasmadrak
    @rasmadrak 2 роки тому +4

    I usually add current seconds (i.e unix time) to any id that is generated. That way it further reduces the risk for collisions without actually checking for one.

  • @yerngames
    @yerngames 2 роки тому

    Great video!

  • @maxemore
    @maxemore 2 роки тому

    And just today I was looking into name mangling and unique random numbers in c++. Right on time

  • @tristansantiagovegan1092
    @tristansantiagovegan1092 2 роки тому

    I love Cherno's videos. I hope that one day he teaches some high math for us! I think that would be fun like a puzzle game.

  • @popplestones886
    @popplestones886 2 роки тому +1

    You do you bro, no need to apologise. I am not even a c++ dev, but loving your videos

  • @rendoirs
    @rendoirs 2 роки тому +1

    Hey Cherno! Great video :)
    I know you have a predefined plan for both Hazel 2D and Hazel, but it would be amazing to have a video on render graphs in Vulkan.

  • @majormalfunction0071
    @majormalfunction0071 2 роки тому

    UUIDs are nice when building assets. It's a way to make a distributed database. Artists 'import' * content, and the build tool picks it up automatically. * not a UE style import, just making a note of { path file type, UUID and friendly name }. The UUID is used in resolving collisions, without checking every DB instance.

  • @joysaha3927
    @joysaha3927 2 роки тому

    Congratulations for 400K cherno! How is alivca btw?? 😃😃

  • @mind.journey
    @mind.journey 2 роки тому +1

    Wow, C++ looks so complicated. The abstractions are crazy

    • @tomg0
      @tomg0 2 роки тому +2

      That’s why I love C lol

    • @mind.journey
      @mind.journey 2 роки тому +1

      @@tomg0 me too!

  • @sam_is_people1170
    @sam_is_people1170 2 роки тому

    thanks!

  • @Ev3r0x
    @Ev3r0x 2 роки тому

    17:44 you should initialize all internal states to produce the best results
    like so:
    std::array seed_data{};
    std::random_device rd{};
    std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
    std::mt19937_64 mt{ seq };

  • @Bagginsess
    @Bagginsess 2 роки тому +2

    Could you consider a short synopopsis video on optimizing physics in conjunction with networking for multiplay games?

  • @r1pfake521
    @r1pfake521 2 роки тому

    A few videos ago you said showcased your C# integration and said that you make a second video about it where you show the implementation, did you not upload the video, because I can't find it.

  • @RPBCACUEAIIBH
    @RPBCACUEAIIBH 2 роки тому +2

    I'm kinda glad you've given up on making this series more... strict, cause the value of your videos is exactly that you're talking about everything that could possibly happen rather then just making a "tutorial" others meant to copy with little to no explanation on why it works the way it does... I wish other tutorials would be more like this, cause I hate to copy, I want to understand, and make my own choices. :)

  • @PeterWraaeMarino
    @PeterWraaeMarino 2 роки тому

    In a engine I have created I can add xref nodes to my scene. these nodes loads other scenes into that node. so I can actually xref the same scene multiple times in my main scene which means the loaded scenes will have uuid that are the same as the other loaded scenes. I made a rule that uuid only have to be unique in sibling relations. How would you handle importing multiple xrefs which is probably called "prefabs" or something in your engine.

  • @davidlloyd1526
    @davidlloyd1526 2 роки тому +6

    Hmm.... If you're going to do a long video on UUIDs, you probably should at least explain how real UUIDs are generated. They are not random numbers - they are defined in RFC 4122 and are a combination of random number, current time and (traditionally, but no longer) hash of hostname/MAC address of the network card.
    Also, I'm pretty sure that just calling the platform GUID generation APIs is preferable to writing your own - probably via Boost. You can always collapse them to a 64bit if you need to...

  • @judedavis92
    @judedavis92 2 роки тому +1

    Are you currently accepting pull requests?

  • @werdox
    @werdox 2 роки тому

    kind of a random question but whats the intro music?

  • @oscardeits4709
    @oscardeits4709 2 роки тому +3

    Hey Cherno, the mt19937_64 is definitely NOT thread safe. The random device is going to be thread safe. All you need to do is make the engine thread local.

  • @paladesilviu-marius1686
    @paladesilviu-marius1686 2 роки тому

    Hey, maybe it isn't a great idea, but isn't it safer to generate UUIDs based on time and date?

  • @Victor_Marius
    @Victor_Marius 2 роки тому

    What I like to use for UUIDs is time and date as timestamp as UInt64 together with a UInt64 random number. And you get 128 bits

  • @nanotechnicianhq
    @nanotechnicianhq 4 дні тому

    I see. So if someone makes a dupe of a weapon in game, it will have the same UUID and even the same assets attached to that UUID. Even though I don't have a background in this, its interesting none the less.

  • @gabrielverde5649
    @gabrielverde5649 2 роки тому +4

    Wow, never been first B4 👀

  • @beqa2758
    @beqa2758 2 роки тому

    What about using current time in nanoseconds as uuid ?

  • @devinschlegel1763
    @devinschlegel1763 2 роки тому

    how would we detect a bug caused by 2 items with the same UUID's

  • @dylanwilliams9860
    @dylanwilliams9860 2 роки тому

    So when generating the objects why don't we use the memory address of the pointer for it? A few points of my thought process: Always unique and bulletproof since the ?C/OS/BIOS/Hardware? is handling it, you can ping any command or expression you could dream of because the name(UUID) is the pointer, when the object goes out of scope its super easy and clean to garbage collect them, and you know their always a set mem-size. Obvious downsides is that it uses a set memory amount that is hardcoded and immutable.

  • @devpartap9748
    @devpartap9748 2 роки тому +2

    Hey Cherno

  • @SimonBuchanNz
    @SimonBuchanNz 2 роки тому +3

    Not sure why you have a problem with combining random values to get bigger random values. Both true and pseudo random sources are modeling bitstreams, so so long as you don't screw up the distribution there's nothing wrong with combining.

    • @mathewsjoy8464
      @mathewsjoy8464 2 роки тому

      No cause with combing you still have a chance of getting a non unique value

    • @SimonBuchanNz
      @SimonBuchanNz 2 роки тому +2

      @@mathewsjoy8464 Not sure you understand what I'm saying? If I have 32 random bits, and then I have 32 more random bits, then I have 64 random bits. And 64+64 bits is 128 bits. That's all.

    • @iivarimokelainen
      @iivarimokelainen 2 роки тому

      @@SimonBuchanNz two consecutive randoms will be the same.

    • @SimonBuchanNz
      @SimonBuchanNz 2 роки тому

      @@iivarimokelainen sorry, what? If random keeps gives you the same value then it's not a very good random.

  • @SelmirAljic
    @SelmirAljic 2 роки тому +1

    Law of murphy!

  • @asandax6
    @asandax6 2 роки тому

    Computer randomly turning on: What I've observed with mine is that if there's any slight change on the electric supply the computer will turn on. What I mean by this is when ever anything else is plugged in e.g a cattle, a stove or a light bulb is turned on the computer turns itself on. I don't know what causes it it might just be my PSU

  • @CoderDBF
    @CoderDBF 8 місяців тому

    Could someone explain to me why memory location can’t be a UUID?
    If you create a million variables, then each variable will have a unique location in memory, so why not use that?

  • @krystofkratky3424
    @krystofkratky3424 2 роки тому

    What about using datetime when entity was created in ms, than you will need just a few characters to make it completely unique

    • @lengors1674
      @lengors1674 2 роки тому

      A possibility, but you still have to account for the fact that that only prevents collisions locally. Other machines can generate the id at the same time with the same extra characters, how ever unlikely that can be.
      Personally, I would create a protocol, so that everytime entities have to be shared among multiple machines, those machines would generate an additional uuid that (uniquely) identifies each machine and append that to the uuid of the entities.

  • @lakshyarajsinghrathore1902
    @lakshyarajsinghrathore1902 2 роки тому

    Hi cherno, i have been following your video series for long and it has been great. I have a request regarding the source code that if you can please upload the source code of the engine below every video till that point the engine has been completed in that video, something like the commit history or similar. I know i am asking much but i think it will greatly enhance the effectiveness of the tutorial series as the whole point of the series is to teach to code game engine. If it could be possible for u please make this update.

  • @liudasaugustinas4401
    @liudasaugustinas4401 Рік тому +1

    I made a test with this and after 2 billion iterations it didn't generate same number i think it's pretty safe to use it

  • @aloluk
    @aloluk Рік тому

    Surely this just needs a body in the header like this?
    template
    void OnComponentAdded(Entity entity, T& comp) {}

  • @traywor1615
    @traywor1615 2 роки тому

    Off topic:
    I had a similar issue with my computer turning on randomly, and found out that my RealTek Audio Driver was going crazy, somehow it emits a wake on lan signal (or is somehow hooked as being able to turn on the computer). There was another issue, that whenever i wanted to switch between my speakers and headphones, it requires me to unplug my headphones, because it somehow bundles them together and overrides by priority (where headphones had a higher one), which i found silly. Turns out if I uninstall RealTek drivers, both problems vanished. Seems like Windows can handle both issues well on its own.
    Though I wonder, why it was the case. The latter I think was connected to which version i was using, but then again, it was the only dedicated one available for my motherboard, and since it works perfectly well without them, I don't saw the need to test a version for generic motherboards. The latter is still weird. I guess the proper solution would be to remove the RealTek Audio Drivers from Wake On Lan List, but in my (short) research, I only found solutions, turning WOL of entirely. Still, why does it turn on? A wild guess would be Single-event upset picked up by the speaker, or other electormagnetic noise (it does beep sometimes when i get a call), however I really poke in the dark here.

    • @marilynman
      @marilynman Рік тому

      Some drives can wake the computer, and in the drivers there can be several options on how to wake it up. Having audio drivers to wake computers up seems weird, but if it's a driver option then it's just a matter of disabling it. I had to disable that option with the ethernet driver as it woke it up with any signal coming from the modem, and I found out that it also had an option to disable the activity lights when it's in sleep mode (that makes it annoying when you are sleeping).
      I recall there is a command function to search for all drivers that have that option turned on. Among them there are the common ones like the keyboard or mouse (touchpad).

    • @traywor1615
      @traywor1615 Рік тому

      ​@@marilynman I actually allready solved this isse. Device Manager -> Network Card -> Realtek PCI Controller -> Energy Stuff -> Then disable waking up or enable it and only allow magic packet (thats what I did).
      The light stuff doesn't apply to me though, because I don't sleep where my PC is.

  • @guywithknife
    @guywithknife 2 роки тому +2

    How I implemented editor state and runtime state with resetting when you stop running is I use two EnTT registries: one that is edited in the editor and the second that is actually executed against at runtime. When you press play, it copies all entities from the editor registry to the runtime registry using EnTT's poly_storage functionality and swaps the runtime registry to be the one that is rendered (and clears the other one to free the memory). When you press stop, it simply swaps the rendered registry to the editor one. I don't need a UUID (for this) as I can use the EnTT entity ids directly (at runtime, it identifies the runtime entity, you never use it in the editor). For named entities (and resource names), I use hashed strings, so names are namespaced, eg "player/weapons/my-gun" and this is hashed to an integer (using EnTT's hashed_string). I use UUID's only as default entity names (as strings -- actually I don't use UUID's exactly, I use something more akin to a nanoid). Either way, I find namespaced hashed strings much more human friendly than UUID's. Named entities just provide a runtime mapping from string name to EnTT entity id.
    PS: I don't like the idea of making a custom unique ID and calling it UUID when its not actually a UUID. Call it a UID or UniqueID or whatever you want, but UUID and GUID have special meaning in the software world, you shouldn't co-opt those well defined terms to something else.

  • @perfectionbox
    @perfectionbox 2 роки тому

    if you can avoid stuff like UE's asset redirectors, more power to you.

  • @S41L0R
    @S41L0R 2 роки тому

    oh so are these like hashIds in botw?

  • @Raul-pg1pf
    @Raul-pg1pf 2 роки тому

    mm, The name kind of reminds me of Haxel Flixel which also serves the same purpose

  • @TheMightyPunion
    @TheMightyPunion 2 роки тому +1

    if the id generated was the date and time it was generated wouldn't the chance for overlap be 0? unnecessary but just a thought.

    • @garageman2236
      @garageman2236 2 роки тому

      You still have the issue of two different machines that could be working on the same project at the same time creating objects at the same time so they would get the same IDs

    • @sablanex
      @sablanex 2 роки тому

      @@garageman2236 but the chance of someone else creating a uuid the exact same millisecond is extremely unlikely.

  • @hakoo2700
    @hakoo2700 2 роки тому

    😉🙂

  • @Jkauppa
    @Jkauppa 2 роки тому +1

    runtime and static entity ids, there is a difference, you are talking about asset ids, editor time

    • @Jkauppa
      @Jkauppa 2 роки тому

      like the buffer of vertices is 0..n, but the asset ids are static

    • @Jkauppa
      @Jkauppa 2 роки тому

      you need to have it statically written in the header file of the editor instance

    • @Jkauppa
      @Jkauppa 2 роки тому

      not in any way done in run time

    • @Jkauppa
      @Jkauppa 2 роки тому

      oh, pre-compiled static identifiers

    • @Jkauppa
      @Jkauppa 2 роки тому

      it needs to always load the same texture, if its statically saved in the entity files

  • @aloluk
    @aloluk Рік тому

    With my 25+ years of games dev experience, i feel like i'm code reviewing you watching your videos :). I also dont like your different more verbose function names when you just add an additional parameter like the UUID. Same as when you converted a type to a string, ithe parameters explain the input to the function young wippersnapper.

  • @shadowlordalpha
    @shadowlordalpha Рік тому

    ah yes... when 4 billion numbers isn't enough

  • @eggmeister6641
    @eggmeister6641 2 роки тому

    yo

  • @NotBojosos
    @NotBojosos 2 роки тому +7

    Why hash the random uint64? Just use the value itself.

    • @laka1469
      @laka1469 2 роки тому +2

      std::hash for integer types is often implemented as the identity function. So it's the same (usually).

    • @ipotrick6686
      @ipotrick6686 2 роки тому

      if you dont hash it you have to search for it in an array! If you make a hashmap you can nearly instatnly look up the entity behind it

    • @NotBojosos
      @NotBojosos 2 роки тому +1

      @@ipotrick6686 I know that. I was just asking why call std::hash() as it seems pointless. We could simply return the uuid and use it as the key.

    • @kirasmith1147
      @kirasmith1147 2 роки тому

      @@NotBojosos std::hash() was to be able to implicitly convert Hazel::Hash to work as a hash value in the unordered map. you could totally just use the uuid as the key, but now you'd never have to worry about the (uint64_t) casting again

  • @aloluk
    @aloluk Рік тому

    When you talk about include order, you say baout configs, but then a couple of lines down is GLM_ENABLE_EXPERIMENTAL which is configuring. Its also really bad to include config defines from headers because you can break ABI if you lpass an object to another cpp which has different defines declared, so the layout of the objects can be different. From experience, that creates horrendously strange and hard bugs to track down.

  • @Tag23456
    @Tag23456 2 роки тому +1

    If the code is not serializing in a deterministic way it will upset version control software.

  • @Positroni
    @Positroni 2 роки тому +1

    Just as a note Mersenne Twister is bit meh as far as pseudo random number generators go, performance of MT is mediocre and statistical quality is not all that great either, it also has kinda huge state but just to make sure it is not bad in any sense just not perfect. For generating UUIDs MT is ok since performance is not all that critical. If one needs absolute perfomance xorshift* or pcg are better with much smaller state and better statistical quality but since those are not included in the standard library one has to copy the implementation.

  • @iivarimokelainen
    @iivarimokelainen 2 роки тому

    this is some insane level of "not invented here" syndrome. Was using stduuid too easy?

  • @afropovic
    @afropovic 2 роки тому

    I just used a library. I'm a terrible person :D

  • @267praveen
    @267praveen 2 роки тому

    Yo ...

  • @jwbonnett
    @jwbonnett 2 роки тому +5

    A typical UUID uses the time, date and random to reinforce prevention of colisions. I see that you only did part of this...

    • @SimonBuchanNz
      @SimonBuchanNz 2 роки тому +4

      That was v1 of GUIDs (the Microsoft UUIDs). It also used the MAC address of your network card. Basically nobody uses that, at least deliberately, anymore, they use v4, which is just random bits except for the version tag.