bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Bevy Preferences API

Open viridia opened this issue 1 year ago • 3 comments

What problem does this solve or what need does it fill?

Games and editors need a way to store user preferences: things like video options, keyboard/controller mappings and so on.

What solution would you like?

I proposal we add an API to Bevy for saving and loading of user preferences.

This should support at least the following features:

  • It should support serde serialization of preference data in some common format.
  • It should allow plugins and libraries to be able to define their own preferences that can be stored along with the app preferences.
  • For desktop platforms and mobile, it would know the correct directory for storing the preferences in the user's home directory.
  • For browser platforms, it should be able to store preference data in browser local storage.

The solution you propose for the problem presented.

What alternative(s) have you considered?

There are a number of existing Rust crates that provide preference-saving functionality. However, these don't necessarily conform to the requirements for a Bevy-based game. For example, some crates may assume that the preferences are stored in the filesystem, which may not be true in a browser-based game.

viridia avatar May 10 '24 02:05 viridia

The API here needs to be carefully considered. The proposal here mirrors that of PlayerPrefs and EditorPrefs in Unity, which is backed by the Windows registry, local storage on Web, and a sqlite storage on other platforms. However, these APIs are notorious for being beginner traps for persistent state as they are always results in blocking disk IO on each call. Accidentally using these APIs in a loop can instantly tank performance, and making the APIs only periodically commit their states to disk may introduce consistency issues in the case of a process crash.

james7132 avatar May 10 '24 03:05 james7132

I've put up a PR. My approach there is to provide a simple typed value store in a bevy resource, using Reflect. Users of preferences don't need to know anything about where preferences are stored, or how they got there. They just need to know the rust type of the preferences they care about, and can get/set/mut.

I'm of the opinion bevy should provide some filesystem backend for this, but make it easy for users to bring their own. We can make the simple cases easy, and the complex cases possible. A simple filesystem backend might be as straightforward as writing to the assets directory, and watching for changes. Both can be done asynchronously without blocking the main event loop.

We can also aim to build a production-ready filesystem backend, but I suspect that will be a significant undertaking.

aevyrie avatar May 10 '24 05:05 aevyrie

I would keep preferences as individual reflect resources marked to be stored/restored as pref:

  • it allows for change detection, you don't need to bridge between them
  • keeps all prefs separated, as for example with the PlayerPrefs api the keyName doesn't have to be unique

And a separate backend which handles the actual storing, restoring of preferences to the local user directory.

I don't know if it would be better to mark them in code, by registering resources to be stored, or if the resource itself should be marked.

As a more long-term solution it would probably a good idea to make a storage api in general, where prefs is a part of, as similar data like save game state, cache, etc. could also be handled this way.

valaphee avatar May 10 '24 11:05 valaphee

@cart has a comprehensive comment laying out requirements and design that's essential reading for anyone tackling this: https://github.com/bevyengine/bevy/pull/13312#issuecomment-2108921673

alice-i-cecile avatar May 13 '24 23:05 alice-i-cecile

Detailed requirements doc here: https://hackmd.io/@dreamertalin/rkhljFM7R

viridia avatar May 22 '24 19:05 viridia

Alice told me to link the crate I made for config files, so here ya go: Crates.io | Github

Pnoenix avatar Aug 06 '24 23:08 Pnoenix

I've written my own lib, which has a somewhat different design: https://github.com/viridia/panoply/tree/main/crates/bevy_mod_preferences

  • Auto-save with timer
  • Saves to standard OS preferences locations.
  • "Safe" saving protects against corruption - saves to a temp file and then renames.
  • Doesn't use the asset system, preferences are available immediately after App::finish().
  • Allows any resource or game state to be saved as a preference - just add the preference annotation to the reflected type.
  • Currently not a stand-alone crate although I plan to do that at some point.

viridia avatar Aug 07 '24 00:08 viridia