Bevyのデフォルトプラグインを理解する


Bevy is

A refreshingly simple data-driven game engine built in Rust
Free and Open Source Forever!


スターターbevyプログラムは次のようになります.
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .run();
}
これはコア機能を追加し、ウィンドウを与えます.
しかし、これらの「デフォルトプラグイン」は何をしているのでしょうか?我々は、ちょうどこのポストでそれを調査します.
プラグインのリストは以下の通りです.
  • LogPlugin
  • CorePlugin
  • TransformPlugin
  • DiagnosticsPlugin
  • InputPlugin
  • WindowPlugin
  • AssetPlugin
  • ScenePlugin
  • renderplugin -機能bevyCountレンダリングで
  • SpritePlugin -機能bevyoundスプライトで
  • pbrplugin -機能を使用して
  • uiplugin -機能bevyount UIで
  • テキストプラグインで
  • オーディオとオーディオ機能
  • 機能と一緒に
  • 機能を備えた
  • WintPlugin -機能bevyount winitで
  • ログプラグイン

    This plugin is really simple, it will add an appropriate logger for your target (e.g. log to console when targeting wasm) and this will allow all logs to go to the right place.

    It can be configured with a resource like this

    app.insert_resource(bevy::log::LogSettings {
        // filter logs lower than ERROR
        level: bevy::log::Level::ERROR,
        // also include INFO logs of module wgpu_core::instance
        filter: "wgpu_core::instance=info".to_owned(),
    });
    

    You can also pass a log config via environment variable RUST_LOG , this will override whatever settings where selected.

    # equivalent
    $ RUST_LOG="error,wgpu_core::instance=info" cargo run
    

    コアプラグイン

    The core plugin doesn't do anything too interesting. It will register some types, setup the time system, and setup the task pool.

    One can use it to create timed systems, e.g. a system that does something every X amount of seconds:

    #[derive(Component)]
    struct Foo { pub timer: Timer }
    
    // startup system to initialize timed component
    fn my_setup(mut commands: Commands) {
        commands
            .spawn()
            .insert(Foo {
                // true to indicate a repeating timer
                timer: Timer::from_seconds(5., true),
            });
    }
    
    // system that does something based on timer
    fn my_system(
        mut query: Query<&mut Foo>,
        time: Res<Time>,
    ) {
        for mut item in query.iter_mut() {
            // progress timers
            item.timer.tick(time.delta()); 
            if item.timer.finished() {
                bevy::log::info!("this prints every 3 seconds!");
            }
        }
    }
    

    TransformPlugin

    This plugin sets up a transform model that allows objects to have a position, described as a hierarchy of parent-children relationships, similar to other game engines.

    Every entity with GlobalTransform and Transform components gets this functionality. The GlobalTransform describes the entity's position globally, and is immutable by the user. The Transform describes the entity position in respect to its "parent" (or the global reference if there isn't one); this is the component we can modify to change an entity's position.

    Whenever a Transform is updated, all its children get updated so their GlobalTransform reflects their new position.


    診断書

    The diagnostics plugin allows us to record any metric of interest, bevy comes with two plugins EntityCountDiagnosticsPlugin and FrameTimeDiagnosticsPlugin that we can use to record some useful data, as well as LogDiagnosticsPlugin , to log this diagnostics.

    // ...
    .add_plugin(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default()
    .add_plugin(bevy::diagnostic::LogDiagnosticPlugin::default())
    

    インプットプラグイン

    This plugin is very straight forward, we can read input events in our systems to react according to user actions.

    As an example, here we are catching all mouse button input:

    fn my_system(
        mut events: EventReader<MouseButtonInput>,
    ) {
        for event in events.iter() {
            if event.state.is_pressed() {
                bevy::log::info!("{:?} pressed!", event.button);
            }
        }
    }
    

    ウィンドウプラグイン

    The window plugin is responsible for 2 things:

    1. Creating a window
    2. Managing window events

    This means that just how we can react to mouse clicks, we can react to window events such as leaving or entering the window:

    fn my_system(
        mut events: EventReader<CursorEntered>,
    ) {
        for event in events.iter() {
             bevy::log::info!("cursor entered!");
        }
    }
    

    We can also define some settings for the window creation:

    .insert_resource(WindowDescriptor {
        width: 400.,
        height: 200.,
        ..Default::default()
    })
    // ...
    

    プラグイン

    This plugin allows us to load any asset and easily use them throughout our program. It features background IO which means our app won't lag from loading assets.

    We can load an asset like this

    fn load_something(
        mut commands: Commands,
        loader: Res<AssetServer>,
    ) {
        // this won't block us until the resource is loaded !
        let image: Handle<Image> = loader.load("image.png");
        commands.insert_resource(MyAsset { image });
    }
    

    And request them like this

    fn use_something(
        assets: Res<MyAsset>,
        images: Res<Assets<Image>>,
    ) {
        // at this point the asset could be loaded or not yet
        if let Some(loaded) = images.get(assets.image) {
            // do something ...
        }
    }
    

    The asset server provides features like filesystem watching, which enables hot reload of assets during development.

    Asset loaders can be implemented for any kind of asset, images, text, anything.


    There are still many more plugins to explore and how they interact with each other, I plan to make more posts about them and also about what using bevy's ECS looks like.