Closed shnewto closed 1 year ago
I keep going back and forth on this topic internally. What defines "visual aspects" of the game is a very subjective thing that varies between projects.
Using this crate, you can save all components (Bevy ones or otherwise) that implement Reflect
. So if you have simple components that don't have any entity references, you can use this crate as-is.
Problems arise when you're dealing with components which reference entities. The main ones being Parent
and Children
.
I have been toying with an implementation of saving/loading Parent
and Children
in this branch:
https://github.com/Zeenobit/moonshine_save/tree/hierarchy
If Parent
and Children
are your only issue, then using that branch should solve your problem. Let me know if run into any issues with it.
If you're using other Bevy/external components that reference entities though, you'll manually have to fix the references. This is mainly why I keep going back and forth on this idea. Because unless Bevy gives us a standard trait for updating entity references, it'd be impossible for this crate to fix references of external types.
We have MapEntities
trait in Bevy, but that doesn't quite work due to Entity generations being dropped during serialization.
@Zeenobit thanks for the thoughtful reply 😄 I don't really know for sure if anything I'm bumping into is related to Parent
and Children
relationships, my experience with those concepts in the code relates mostly to spawning nested UX elements which isn't my use case. I did bump into issues with meshes and materials which is maybe related to your comments about updating entity references? i.e. the handles for meshes and materials save but that's not useful information on load... and the bevy Mesh
object doesn't derive or implement Reflect
so it's even further out of the scope for this crate I think.
My use case at the moment is generating a bunch of little emissive icospheres of various sizes. Saving their positions that are otherwise generated using some noise algorithms, is definitely a time saver. And adding the meshes and materials isn't really any overhead for me.
I'm happy to use your crate for the wins I'm already seeing, and for you to close this issue if you'd like. I do sort of think if there are cases where actually batch spawning is possible (instead of just inserting resources) there would be some convenience in it but I tend to agree that it's probably a moving target.
Thanks again!
Just check the definition of the components you're using. If they derive Reflect
and don't have any Entity
members, or members that have Entity
members, then you can stick that component on an entity with Save
and save/load should work just fine with this crate.
Otherwise, you'll have to manually fix the references, or put that data into a separate entity and don't save it (i.e. spawn it after load).
Any Transform
component, for example, would be saved fine. For meshes, I haven't personally tried it. I suspect it may have something to do with mesh resources being saved/loaded. I'd be happy to look into a (non)working example and see if I can/should integrate support for it in this crate like Parent
/Children
.
Ah happy to provide a basic example of my current approach, i.e. saving a bundle, grabbing the transform from the loaded data then creating meshes and materials and spawning
I checked your repository, and I don't see any issues here. As long as you have a "flat scene" (i.e. no child entities), and you load the same assets as the ones used when saving, saving a basic scene with all the visual elements should be fine with this crate.
If you do decide to have a hierarchy (i.e. set parents, add children), then I recommend grabbing the hierarchy
branch I mentioned earlier.
ah right, yeah that example is how I have it working now, and I'm totally happy with it like that.
my idea when opening this ticket though was that maybe this code
load_from_file(SAVE_FILE_PATH).in_schedule(OnEnter(AppState::CreateMeshesAndMaterials)),
create_meshes_and_materials.run_if(in_state(AppState::CreateMeshesAndMaterials)),
spawn_geometry.in_schedule(OnEnter(AppState::SpawnGeometry)),
setup_camera.in_schedule(OnExit(AppState::SpawnGeometry)),
could be pruned down to
load_from_file(SAVE_FILE_PATH).in_schedule(OnEnter(AppState::CreateMeshesAndMaterials)),
setup_camera.in_schedule(OnExit(AppState::SpawnGeometry)),
i.e. the load_from_file
could handle the "create meshes and materials" and "spawn geometry" for me
well, not quite do the work of "create meshes and materials" for me, more like "load the saved meshes and materials" so I wouldn't have to create them when the app starts. I do think though, that's probably well out of the scope of the utility this crate offers
Yah that's not something I want to support in the save system out of the box, because it'd be hard to come up with a generic solution for it. For example, would the save system store the paths to the assets, or the physical binary data? I think those are problems that are more project-specific for a generic crate to handle them.
I'm pretty much on the same page as you now. I am wondering a bit now though, whether there's a path in bevy for a crate to basically export only tagged components in a scene to a straight up gltf or glb file. If I create a 3d scene in blender for instance, I can export a gltf that contains all the mesh/matieral/transform data and load it in a bevy app, so maybe it could go the other way 🤔
anyway, thanks for the conversation and your willingness to entertain my questions! feel free to close the issue if you're feeling satisfied with things (I am)
Hello! This is a really fantastic crate, and what feels like a really ergonomic solution for picking out the specific components in my scenes I want to save 🤩
In the docs I noticed this comment:
But for me, it'd be really useful actually if there was some capability to spawn game visuals on load in a startup system. In my app, it's not exactly difficult to reconstruct and spawn each visual object from the saved data (3d shapes with some state), it just seems like it would be convenient if I didn't have to 😆
Feel free to disregard and close this issue if it's just not a use case you're looking to address :)
Thanks!