Mastering plugin loadings in Bevy - Part 2/2

In the previous article, we've learn how to create a basic plugin, how to use it and how to load multiple plugins as a group of plugins.

We discovered native DefaultPlugins and MinimalPlugins, which both load the most used native plugins.

But what if you want to disable one plugin of the DefaultPlugins group? and what if you want inject your plugin in an existing group and specifically load it before or after another plugin of the group?

In this article, we'll review some functions provided by Bevy that allow you to do some plugin-loading tricks.

The add_plugins_with function

add_plugins_with function allows you to load a PluginGroup the same way add_plugins does but also receive a function as the second parameter to modify the way the plugins of the group will be loaded.

This allows us to disable a plugin:

fn main() {
    App::new()
        .add_plugins_with(DefaultPlugins, |group| {
            // Disable the LogPlugin 
            group.disable::<bevy::log::LogPlugin>()
        })
        .run();
}

Note that the disabled plugin will still be bundled into the final build, the functionalities of the plugin will just remain muted

⚠️ The add_plugins_with function fully replaces the add_plugins method, you don't need to call it in parallel. To be crystal-clear, this is wrong and will panick:

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins_with(DefaultPlugins, |group| {
            group.disable::<bevy::log::LogPlugin>()
        })
        .run();
}

Or add a custom plugin in the group.

fn main() {
    App::new()
        .add_plugins_with(DefaultPlugins, |group| {
            group.add(HelloWorldPlugin)
        })
        .run();
}

This use case is probably not the most useful because our custom plugin will just be appended to the group, so it will basically do the same as below:

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(HelloWorldPlugin)
        .run();
}

If the added plugin needs to be loaded specifically before or after another plugin of the group, there are also functions to do that:

fn main() {
    App::new()
        .add_plugins_with(DefaultPlugins, |group| {
            group
                // Adds the HelloWorldPlugin before the AssetPlugin 
                .add_before::<bevy::asset::AssetPlugin>(HelloWorldPlugin)

                // Adds the FooPlugin after the ScenePlugin 
                .add_after::<bevy::scene::ScenePlugin>(FooPlugin)
        })
        .run();
}

Sometimes, a plugin of the group can be disabled by the author of the PluginGroup or you may yourself need to disable/re-enable it, to do that you can call the enable function:

// A PluginGroup with a loaded but disabled plugin
pub struct HelloWorldPlugins;

impl PluginGroup for HelloWorldPlugins {
    fn build(&mut self, group: &mut PluginGroupBuilder) {
        group
            .add(PrintHelloPlugin)
            .add(PrintWorldPlugin)
            // Disable the just loaded plugin
            .disable::<PrintWorldPlugin>();
    }
}

fn main() {
    App::new()
        .add_plugins_with(HelloWorldPlugins, |group| {
            // Enable it from your app
            group.enable::<PrintWorldPlugin>()
        })
        .run();
}

As of today, this is all the functions that could be called externally from the PluginGroupBuilder, excepts the finish method for which I did not find any use case to call it externally from your app.

I hope you enjoyed this article!

Comments

Be the first to post a comment!

Add a comment

Preview