Crate bevy_proto_resource_tuples

Source
Expand description

A prototype for working with Resources in groups.

Initial PR

§Usage

use bevy::prelude::*;
use bevy_proto_resource_tuples::*;

#[derive(Resource)]
struct ResourceA;

#[derive(Resource)]
struct ResourceB;

#[derive(Resource, Default)]
struct ResourceC;

#[derive(Resource, Default)]
struct ResourceD;

fn main() {
    App::new()
        .insert_resources((ResourceA, ResourceB))
        .init_resources::<(ResourceC, ResourceD)>()
        .run();
}

§Motivation

With Bevy 0.10 and the upcoming 0.11 releases, it is possible to use add_systems to add multiple systems at once, instead of making multiple calls to add_system. Likewise, there are changes underway to add multiple plugins at once.

Just as those interfaces were changed to minimize calls, init_resource and insert_resource calls can also be minimized, in order for the interface to be homogenous.

This is a bit controversial; the primary concern is that by grouping resources, it in a way implies that resources form “groups”, rather than being separate objects. This differs from groups of systems, where there are operations over groups of systems, while there aren’t any operations to be done over groups of resources, since they are each unique pieces of data.

It appears that some view add_systems as a tool only for working with groups of systems that have common attributes (and then making separate calls for unique systems), while others see it as a tool for adding systems in batch.

In reality, there is nothing stopping anyone from using add_systems either way. But from the perspective of those who use it simply to batch calls and lower LOC, the lack of insert_resources and init_resources feels rather inconsistent. Also, if these methods were added, there’s nothing stopping users from making separate calls like before.

tl;dr: The benefit of these methods is that they bring consistency and usability without preventing users from doing stuff in the old style or mixing styles to what feels appropriate.

tl;dr for the tl;dr: More user freedom.

§Limitations

Because this prototype is a separate crate, I can’t implement the traits for the base case (P0) due to orphan rules. So when working with a single resource, it’s necessary to call init_resource/insert_resource.

§Patterns

The following are some patterns enabled by these changes. Whether or not they are useful is up to users to discover in practice. Either way, these are very niche, but perhaps they have some use cases.

// It's now possible to init many resources and get their ids all at once.
let [a, b, c] = world.init_resources::<(A, B, C)>();
// It's possible to create type aliases for multiple resources.
type MyResources<T> = (Foo<T>, Bar<T>);

app.init_resources(MyResources<i32>);

Structs§

InitResourcesCommand
Command for init_resources.
InsertResourcesCommand
Command for insert_resources.

Traits§

AppInitResources
Extends App with init_resources.
AppInsertResources
Extends App with insert_resources.
CommandsInitResources
Extends Commands with init_resources.
CommandsInsertResources
Extends Commands with insert_resources.
InitResources
Resources that can be initialized in the World together.
InsertResources
Resources that can be inserted into the World together.
WorldInitResources
Extends World with init_resources.
WorldInsertResources
Extends World with insert_resources.