bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
35.01k stars 3.43k forks source link

Bevy Preferences API #13311

Open viridia opened 3 months ago

viridia commented 3 months ago

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:

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.

james7132 commented 3 months ago

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.

aevyrie commented 3 months ago

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.

valaphee commented 3 months ago

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

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.

alice-i-cecile commented 3 months ago

@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

viridia commented 3 months ago

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

Pnoenix commented 1 month ago

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

viridia commented 1 month ago

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