bevyengine / bevyengine/bevy

Prerequisite plugins and resources / dependency handling: `.require_plugin()` and `.require_resource()`.

Open
#14,192 1 comment 0 reactions 0 assignees View on GitHub
A-App C-Feature X-Contentious
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

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

Bevy does not currently provide an ergonomic way to handle prerequisite plugins / resources in the same fashion of similar initialisation / configuration concerns of apps.

Adding plugins and resources that may or may not already be added to the app requires condition checking outside of the usual chain of `app.add_plugin(...).insert_resource(...).` etc. that you would have in `Plugin::build()` or `main()`.

Often this is done for setting up prerequisites, such as plugins which rely on `egui` checking to make sure `EguiPlugin` is added.

In these cases, a bit of semantics is lost in the code, which may obfuscate the code-writer's intent. It also unnecessarily separates initialisation logic into multiple parts of your code.

For example, the following patterns are very common:
```rs
fn build(app: &mut App) {
app.add_systems(Update, ui_update);

if !app.world.contains_resource::() {
panic!("UI Settings not present. Please provide a UiSettings resource!");
}

if !app.is_plugin_added::() {
app.add_plugins(EguiPlugin);
}
}
```

## What solution would you like?

I propose `App::require_plugin::(auto_init: bool) -> ?` and `App::require_resource::(auto_init: bool) -> ?`. The `?` type here _could be, for example,_ a `Result` for better error checking.

These functions would perform the same sort of checking in the code above, but making the code more concise and better preserving semantics / intent.

Example:
```rs
fn build(app: &mut App) {
app.add_systems(Update, ui_update)
.require_resource::(false)
.require_plugin::(true);
}
```

Additionally, `.require_*` functions may be able to _log_ that a panic was caused due to a dependency error, which may or may not happen when using the current method of manually checking - particularly if dependency checking is done many times throughout the code and the developer has forgotten to write sufficient logging logic.

## Issues with this solution

- **Running additional code along side requirement checks.** *Example: Attempting to manually initialise a resource/plugin outside of its `Default` constructor, altering the app initialisation if a resource/plugin is not present, etc.*
- **Does not work with Plugin sets.** I'm not a pro Rust developer, but I'm pretty sure the following, although pretty, would not be possible: `app.require_plugins::<(EguiPlugin, PlayerPlugin, ClientPlugin)>()`. Maybe another solution than the one proposed would allow similarly ergonomic code.
- **Is this in the scope of Bevy's concerns?** Although this is a very declarative approach, and does provide an ergonomic benefit to the developer, whether or not this is bloat or is better left to a third-party crate is questionable.

## Additional context

Many other languages and frameworks such as [PHP](https://www.php.net/manual/en/function.require.php), [NodeJS](https://nodejs.org/api/modules.html#requireid), [Lua](https://www.lua.org/pil/8.1.html), [Elixir](https://hexdocs.pm/elixir/main/alias-require-and-import.html), etc. have implemented requirement handling for conditional initialisation of external code.

This too alleviates the need for manual checking, and makes the intent of the code more clear.

## Additional additional context

If this gets accepted and the behaviour / implementation details are decided upon, I'd be more than happy to create a PR with my implementation :)

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the proposed App::require_plugin and App::require_resource entry points and the example dependency-checking patterns in the issue. Clarify the return type, auto-initialization behavior, plugin-set support, logging, and whether this belongs in Bevy before identifying implementation files. Done means an agreed API and scope, rather than only a patch for the examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.