Saving and Loading Scenes! | Game Engine series
Вставка
- Опубліковано 22 жов 2020
- Patreon ► / thecherno
Instagram ► / thecherno
Live Stream ► / thecherno
Hazel ► github.com/TheCherno/Hazel
Twitter ► / thecherno
Discord ► thecherno.com/discord
Series Playlist ► thecherno.com/engine
#Hazel
Honestly my favourite programming series on the internet. I wouldn't even expect this level of quality from a paid course, never mind a free UA-cam series. Thanks!
for new version of yaml-cpp just add a #define YAML_CPP_STATIC_DEFINE before including in any file,
and turn on staticruntime in premakefile of yaml-cpp
@yu_a_vi4427 for some reason it is still giving me linking errors
Thank you so much for keep doing these, you are making my dream of becoming an engine programmer actually posible.
Im watching both and imo the incremental copy and paste is great because you explain the core of it, and the code isnt too complex to understand
Another thing to note (I'm not sure if this is covered later) is the scene is being deserialized in inverse order in which the original entities were added to the scene. You can see this by the original scene has the red square on top, covering the green square. When deserialized, the green square is on top. You can either serialize your entities backwards, or deserialize them backwards. I think deserializing backwards is better, because then the serialized file will match the order of your hierarchy panel. To deserialize backwards, you can make a vector of the entity nodes and then get a reverse iterator to that vector:
auto entitiesNode = data["Entities"];
// reverse it to add the entities in the order they were
// originally added
std::vector entitiesRev(entitiesNode.begin(),
entitiesNode.end());
for (auto it = entitiesRev.rbegin(); it != entitiesRev.rend(); ++it)
{
s_deserializeEntity(*it, mp_scene.get());
}
Have fun!
I had to define "YAML_CPP_STATIC_DEFINE" in the premake for the newer version of YAML, otherwise it will try to compile as a DLL
It now build yaml project but cant link it to engine... there are errors like unresolved external dllimport...
@@p3rk4n27 maybe the engine compiles as a .dll instead of a static .lib
@@mjthebest7294 where did you put define? Engine or yaml project? I tried in yaml
@@p3rk4n27 inside yaml premake
@@p3rk4n27 Have you solved this problem, please
27:21 Great thanks to you, CHERNO!
I just implemented binary serialization/deserialization for my application with the cereal library. I read that was the fastest for CPP. Pretty cool stuff.
I think copy paste is not an issue, you explain everything very good and understandable way.
THE BEST!!!
Serialization: In computing, serialization or serialisation is the process of translating a data structure or object state into a format that can be stored or transmitted and reconstructed later. From Wikipedia
The code at 14:55 "m_Registry.each([&](........)" is deprecated in recent versions of entt. I used for iteration with registry.storage(): "for (const auto [ent, ref] : m_Scene->m_Registry.storage().each()) {...}. You can use the first element in the tuple (ent) as entity handle, which it is. I used because every entity has it. In the future i'm going to change it to or something like that, I presume.
Is there any reason you've implemented this without reflection? Or is it just simplicity? For my engine I've added simple metaprogramming to allow for reflection, which means I don't have to write deserializers for every member variable, or write code to show it in the editor.
@@mattmurphy7030 "gamedevs" are allergic to template metaprogramming
how?
He doesn't have a clue
@@erniegutierrez410 lol every game dev bitches about templates
Yes. Reflection information makes this a breeze.
I'm wondering how animation and hierarchical entity updates are going to work in an ECS? Do you just do an animation pass outside the ECS?
I start to really really miss the code tooling around the engine. It starts to look very "feature rushed" with UI and now Serialization hand written without a modular way of adding HUDs / Serializers. I think that we miss some architecture requirement (Registry & Metaprogramming) to allow the GPP to declare new components & register tools around them (HUD, Serializer). Then have the Entity Inspector use the Registry and rely on the user provided ImGui Widgets to do the job for us. Same with Serialization. I understand that at it's current state and for the sake of simplicity on YT it's probably not done (plus you can show more concrete features and not "tool" code). But I'm no beginer and making a Registry the right way is my current challenge, here I see all the applications where I should use it, but I still don't have a clue on how to achieve that. I'm sad :'(
I've found that with these things, the most important thing to decide is the interface, and I like his view that serialisation is something external and to minimize its presence in the core code base. Once he's settled on an interface, the next task is to write something that works, and only after that it's time to start thinking about useful abstractions and modularizations. This last bit can easily take three or five times as long as the bit where you just got something to work, and you've gotta be ready for that. You're not gonna do it right first time around.
I want to emphasize the _useful_ abstractions. I think you should almost always begin with a procedural implementation, and only when the code screams that it wants to be turned into objects is when you should consider doing it. If it's possible to implement and maintain the entire Python language or the Linux kernel in C, then clearly objects are not _needed_ for writing maintainable code, even in gigantic code bases. Starting in the other end, i.e. by defining the objects first and writing code around them later, usually gets you stuck in a code base with bad abstractions and unnatural interfaces.
@@mattmurphy7030 Nah. Simple reflection code can be written in a weekend.
@@johnjackson9767 I hate to bump this thread but how can C++ reflection code be written? As far as I'm aware there's no such think as true C++ reflection.
thanks!
hey cherno please tell how you can easily resolve merge conflicts in scene files
Oh neato! Maybe you’ll actually see this. Thanks for making all of these videos. I’m not making an engine but learning how this stuff works is invaluable.
Is there any reason why you didn't take same approach as with vec3 and apply it to Entity, Scene e.t.c.
I mean by implementing operator for serialization.Maybe apply same to Entity components. Then instead of long method with IF statements to check component it will just call these operators. Or there is something to do with type inference from array of components? Thank you for your video series!
P.S. Friendly reminder to drink water, stay hydrated dude :) I thought you coughing because of that
@@mattmurphy7030 I'm not coding in cpp so I don't know if it's gonna work there and be best practices, maybe there are some pitfalls. I'm coding Swift, and language encourages you to implement it this way.
Hey whats the diffrence between Hazelnut and Hazel ? I missed the last few streams ;)
Hazel is the engine/runtime itself, Hazelnut is the editor UI
(iirc) Hazel is the engine and Hazelnut is editor
Thanks guys =)
ProjectionType should be serialised to a string as well instead of your enum as int. Since you're doing this for readability. It makes your enums more robust when serialised as well.
did you push to GitHub I didn't see the changes
My god!
I was afraid of serialization and deserialization, thought it was too complicated, until now. Thanks for the in-depth video!
nice
Hey Cherno why dont you analyse the new Assassins creed valhalla updated engine video. They released an updated final product and it looks pretty amazing.
was wondering when you were going to add the c#(or whatever tbh) scripting layer because having to write directly in engine is kinda scaring me away from starting a project on hazel since working in engine is so easy to mess something up!
Native scripting is essentially just adding code to the engine. It's good when you don't have to worry about internal engine-related stuff.
@@akshayazariah It's been long since last time i heard about that term!
@@akshayazariah having the buffer between me and the engine just eases the stress of worrying about the stupid stuff like naming conflicts ect and also having a scripting layer is easier than c++
@@khaledhn1 Totally agree. That's why I have a Haxe scripting layer for my C engine. During the development, the game is run in a highly-optimized virtual machine, and all of the code is transpiled to highly-portable C code for release builds. This allows for the game to run "natively", without having to deal with naming conflicts and whatnot like you specified.
Soon! Hazel-dev has had C# for a while now, you can see a demo of it in this video: ua-cam.com/video/g9HGp3icrIg/v-deo.html
Not sure if you see these or not, but you should do a review of the Scorn gameplay on Xbox series X. I know you said you haven’t done a lot of Xbox stuff, so throwing it out there. Some very ‘interesting’ art.
How do you save scripts tho?
In C++ we have access to the raw memory, so would it be possible to make a "screenshot" of the memory and just dump that into a binary file? So the loading is just mapping the file into the memory? If we can't because of the dynamic allocations, would it be possible, for example, to make every allocation in the engine go through a custom allocator that knows where all blocks are so they can be saved and restored on demand? I have seen something like that in Handmade Hero
If the classes only had trivial types and no need for bounds or validity checking then yes, but because these classes hold pointers and references to other objects, those objects will not be in the same place in memory the next time the app loads (the process will get a completely different randomized address space for its working set) so they would need to be manually processed anyway.
The real question is why he would hand-code every class and every member when you could use reflection to just enumerate over the fields in every class? Adding a member to a class now requires writing UI code, serialization code, and deserialization code. Just home off the fact the the member is public and assume it should be (de)serialized.
Why dont you just implement YAML
Hahahahaha this is great... Im following this series but using d3d11
👍👍👏👏
can you do new series for diretX api
Many of us don't know how to work with make files 😅
A video about make, cmake, or premake will be great 💙
@@blfunex I dont think it was an episode by its own, or I would notice it
Woah! Never knew about it. Thanks a lot :)
I'm fine with you copy pasting code as long as it's simple repetitive stuff.
Third, and you are great man
With the new version of yaml-cpp, you need to change staticruntime to "on" in premake file of yaml-cpp project
Hey, I heard you coughing 3 times during this stream... U sure u alright, mate?
Babushka green square
So who's gonna use hazel when It launches, I know I will
First!! And love your vids!
Third.
But you probably don't care.
Oh, so your a Game Engine creator? Name every game engine.
Why would he?
@ACES STUDIO That's not r/wooosh.
If you feel that the code is complicated and/or requires some leaps of intuition for someone going through it first time, You might do well not to copy and paste but instead write it all. Otherwise yeah this is fine.
The stream syntax is so painfully verbose. If anyone is still following along - I recommend you do fingers a favor and do something like this:
#define KEY(x)
Please don't copy and paste, typing it out is way better.