Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Managing Scripts

Scripts live in the standard Bevy assets directory. Loading a script means obtaining its byte representation and associated language.

Evaluating a script means:

  • parsing the script body,
  • and creating or updating the resources which store script state (i.e. context)

Script attachments

Script attachments represent both the context in which a script "lives" and is executed, as well as its "residency identifier".

Scripts can be attached either:

  • to an entity via ScriptComponent's (i.e. ScriptAttachment::EntityScript)
  • or by being statically activated against their script assset (i.e. ScriptAttachment::StaticScript)

When you insert/remove ScriptComponent's, ScriptAttachedEvent and ScriptDetachedEvent's are sent and processed by the script pipeline.

Other attachments, like static scripts have to be manually triggered via AttachScript and DetachScript commands.

Loading

Scripts can be loaded into memory via the AssetServer.

let handle = asset_server.load::<ScriptAsset>("my_script.lua");

Or scripts can be created in memory.

let mut script = ScriptAsset::from("x = 0".into());
script.language = Language::Lua;
let handle = script_assets.add(script);

This will not evaluate any code yet.

Evaluating

A script does not participate in any callbacks until it is evaluated, to evaluate a script you must first attach it to an entity, or to a static script entry.

To evaluate a script, add it to a ScriptComponent manually attach it.

Load File via AssetServer

#![allow(unused)]
fn main() {
extern crate bevy;
extern crate bevy_mod_scripting;
use bevy::prelude::*;
use bevy_mod_scripting::prelude::*;

fn load_script(asset_server: Res<AssetServer>, mut commands: Commands) {
    let handle = asset_server.load::<ScriptAsset>("my_script.lua");
    commands.spawn(ScriptComponent(vec![handle]));
}
}

Create ScriptAsset and Add It

#![allow(unused)]
fn main() {
extern crate bevy;
extern crate bevy_mod_scripting;
use bevy::{asset::Assets, prelude::*};
use bevy_mod_scripting::prelude::*;

fn add_script(mut script_assets: ResMut<Assets<ScriptAsset>>, mut commands: Commands) {
    let content: String = "x = 0".into();
    let mut script = ScriptAsset::from(content);
    script.language = Language::Lua;
    let handle = script_assets.add(script);
    commands.spawn(ScriptComponent(vec![handle]));
}
}

Static Scripts

You can use attach and detach commands, which will run the script pipeline, repeatedly until the requested script attachments are processed. If you don't want to incur big frametime slowdowns, you can instead send ScriptAttachedEvent and ScriptDetachedEvent manually, and let the pipeline pick these up as normal.

Attach a static script

#![allow(unused)]
fn main() {
extern crate bevy;
extern crate bevy_mod_scripting;
use bevy::{asset::Assets, prelude::*};
use bevy_mod_scripting::prelude::*;

fn add_static_script(mut asset_server: ResMut<AssetServer>, mut commands: Commands) {
    let handle = asset_server.load(script_path);
    commands.queue(AttachScript::<LuaScriptingPlugin>::new(
        ScriptAttachment::StaticScript(handle)
    ))
}
}

Detach a static script

#![allow(unused)]
fn main() {
extern crate bevy;
extern crate bevy_mod_scripting;
use bevy::{asset::Assets, prelude::*};
use bevy_mod_scripting::prelude::*;

fn remove_static_script(existing_handle: Local<Handle<ScriptAsset>>, mut commands: Commands) {
    commands.queue(DetachScript::<LuaScriptingPlugin>::new(
        ScriptAttachment::StaticScript(existing_handle)
    ))
}
}

Unloading

When you no longer need a script asset you can freely unload it as soon as it has been loaded, but the script attachment will persist. In order to trigger the on_script_unloaded etc. callbacks, you need to remove the script from the ScriptComponent or detach it manually via DetachScript if it's static.

Once the last script in a context is removed, the context itself will also be removed.

Hot-loading scripts

To enable hot-loading of assets, you need to enable the necessary Bevy features as normal see the bevy cheatbook for instructions.

Assuming that hot-reloading is enabled for your app, any changes to script assets will automatically be picked up and the scripts re-loaded.

File Extensions

Normally the set of supported extensions is pre-decided by each language plugin.

I.e. Lua supports ".lua" extensions and Rhai supports ".rhai" extensions.

Scripts are mapped to the corresponding language plugin based on these and so it is important to use them correctly.

If you would like to add more extensions, you need to populate them via app.add_supported_script_extensions.

    app.add_supported_script_extensions(&[".pua"], Language::Lua);