Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save Games #18

Open
thombruce opened this issue Sep 30, 2023 · 10 comments
Open

Save Games #18

thombruce opened this issue Sep 30, 2023 · 10 comments
Labels
ui Inputs, menus and the like
Milestone

Comments

@thombruce
Copy link
Owner

While there is fundamentally no information worth saving yet, I figure it is a system we probably want to implement early and expand as we go.

The save system will only grow, I mean, as more and more data points need to be persisted. Seems saner to implement the system while we have, say, a single data point to record than to wait until we have hundreds and must fumble through a solution.

I want this system in place not too long after the first saveable bit of information is introduced1.

Footnotes

  1. Technically we could already save ship position, and perhaps its current angular and linear velocities so that the game could be pretty much loaded back up as it was when the player quit. But given that space is currently perfectly uniform, it doesn't make much material difference to do so. Maybe the first saveable piece of information comes after the addition of planets to the system, at which point saving player position become more meaningful.

@thombruce thombruce added this to the v0.1.0 milestone Oct 4, 2023
@thombruce
Copy link
Owner Author

Save game should save:

  • GameTime resource
  • Ship position (possibly also angvel and linvel)
  • ...

From those (at time of writing) two values (four if you include angvel and linvel), I believe we can derive exactly the same state as was saved. Planet positions only require GameTime to be consistent, which it is - that's why I created that resource.

@thombruce thombruce added core New feature or request ui Inputs, menus and the like and removed core New feature or request labels Oct 11, 2023
@thombruce
Copy link
Owner Author

Different options worth assessing:

For just settings persistence: https://github.com/tecbeast42/bevy-settings


I am currently trying to get bevy_common_assets working as part of #70 - still struggling there (mostly setup but I can't print the data from the file - no obvious errors). I am unsure if it is suitable for persistence back to file, or if it is only useful for loading from a file.

I think I should assess save/persistence options in tandem with loading configs from files.

Ideally we just need one library to handle everything we want in this domain... no sense introducing more dependencies than are needed.


It might be worth looking at just doing this with Serde, Ron and Bevy's asset_server. Can that really be so hard? I suppose I have no idea how to persist that way, but I bet I could figure out the loading from file part.

bevy_pkv is definitely worth a deeper look! But I think all options are - that one's just grabbing my attention right now.

@thombruce
Copy link
Owner Author

We've now added two other systems that load configs from file:

  1. A game config file (verse.config.ron)
  2. i18n translations courtesy of bevy_fluent

While neither of these are "save games", either system could inform the approach taken here.

I think we'll do #34 first, as this will give us even more information about how we persist data to a file.

@thombruce
Copy link
Owner Author

Both bevy_pkv and bevy_save talk about creating a save "in the appropriate location for your system".

PKV is a key value store, sort of like an in-memory database that can be written to and read from and then persisted whenever.

Save claims to save the entire game state; resources, entities, etc. etc. or something quite like this (if I'm understanding it correctly). To my mind, this doesn't necessarily offer the granularity we would like and it could result in massive save files as we intend to save various bits of state for an entire galaxy...

Moonshine Save offers more granularity and a component-based approach. It also allows for us to define our own save pipelines and fully specify the filepath (though whether this is relative to a system-specific root, I am unsure).

BevyPersistent is similar to Moonshine Save

And Bevy Settings works similarly to the first two in that it saves to a specific location per system but it concerns itself only with settings - not really relevant here.

I think I want to look in more detail at:

  • PKV
  • Moonshine Save
  • Bevy Persistent

The second two are very similar. PKV is a standout for its key-value database design that could be tremendously useful at larger scales.

@thombruce
Copy link
Owner Author

Narrowing it down to PKV vs Moonshine Save. Very different approaches, I just need to work out which is more appropriate for my needs... and I think it's probably PKV given that I want to have this large, expansive and persistent world with values changed/saved/loaded fairly constantly.

@thombruce
Copy link
Owner Author

So...

Moonshine is a lot more hands-off and sort of "done for you". You add components to bundles defining the save behaviour and for every component that derives Reflect it will save that component into a .ron file at a location specified by the save pipeline. This requires some special case setup for sprites and visuals which ought to be omitted... It's there in the docs.

It's an elegant system, certainly highly configurable... but maybe too hands-off for my liking.

Bevy PKV is more granular. We can save either individual values or structs containing many values to individual keys and we can retrieve those values individually later... We can save and retrieve what we want when we want, we can save as little or as much data as we feel we ought to. The scope of what is saved is distinctly separate from the scope of the game's entities (no deriving Reflect and having this all happen automatically).

Example Use Cases

  • Moonshine Save looks GREAT for saving the entirety of a game, player or level state to a file and loading it fully from that file as and when needed
  • Bevy PKV offers more granularity and is ideal for persisting bitesize bits of data as and when necessary

If we went with Moonshine Save, we would inevitably have to setup many different save and load pipelines to handle the individual parts that needed saving and loading dependent upon where we are in the galaxy, on a planet, etc. Right?

Whereas in PKV, we sort of simply lookup the values in the data store when and where they're necessary.

Moonshine is good for smaller, more traditional, less customisable and granular games (e.g. more Mario than Minecraft).

PKV looks great for broadly customisable, expansive worlds (e.g. Minecraft).

There are ways to coerce Moonshine into doing the same sort of thing... For instance, we could have a save and load pipeline that it is aware of the grid position currently being altered (saving world data into chunk-specific files).


I still can't decide. It sounds vaguely like I'm leaning more towards PKV, but I don't know...

Moonshine Save also has the benefit of being able to specify the name and location of the save file (whereas PKV uses OS-specific locations that are non-configurable [there is a migration.rs example for migrating data if keys or values need to be changed]), so Moonshine arguably has more manageability and simplicity in that sense.

I also believe it would be easier to migrate FROM moonshine TO pkv than the other way around, so I'm tempted to use Moonshine initially and see whether we encounter limitations that justify a switch to PKV a ways down the line.

@thombruce
Copy link
Owner Author

I do believe we'll initially use Moonshine. It's relatively new but has surged in popularity and has a higher code frequency, sooooo... while that doesn't guarantee long term stability and support, it is indicative of community trust and... yeah, I think it's more useful to me right now.

PKV might be more suitable or even necessary later on, but I do believe I'll have an easier time starting with Moonshine and migrating in that direction than the other way around.

@thombruce thombruce added this to Verse Nov 6, 2023
@thombruce thombruce moved this to Inbox in Verse Nov 6, 2023
@thombruce thombruce moved this from Inbox to Todo in Verse Nov 6, 2023
@thombruce
Copy link
Owner Author

Mentioned in #13, let's also add and save a PlayTime resource here. We may not display or use this initially, but it could be useful in future for adding a survival time multiplier to final score or just showing the player how much time they've logged playing.

@thombruce
Copy link
Owner Author

PlayTime resource added as of 6148d5f

@thombruce
Copy link
Owner Author

Short term, we only need to save:

  • High Score(s)
  • Play Time

Long term, we will also need:

  • Player Entity and Transform (translation & rotation)
  • Game Time
  • Enemy/NPC Entities and Transforms (translations & rotations)

And in the distant future, when these things exist:

  • Inventor[y/ies]
  • World gen settings
  • World alterations (how the player and NPC has influenced the generated world)
  • And on, and on, and on...

Could be a lot.

I'm still not sure what save format we employ in the long term, but for the short term where we only need play time and high scores, we're going to simply serialize and deserialize from a file for now (much in the same way we already handle loading config - my hope is that this also informs our approach to saving config from the game itself).

This will be impractical in the long term, but will serve us just fine for a while.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ui Inputs, menus and the like
Projects
Status: Todo
Development

No branches or pull requests

1 participant