#bevy_mod_scripting
2116 messages ยท Page 3 of 3 (latest)
I figured out how to invoke a callback, waited for the "reached final state", then got the same error on add_system
at least I know register_callback is working
now is this of any relevance? I tried printing the system names in the part where it looks for the created system and got this
DEBUG bevy_mod_scripting_core::script_system: Found a system with name "<Enable the debug feature to see the name>"
DEBUG bevy_mod_scripting_core::script_system: Found a system with name "<Enable the debug feature to see the name>"
DEBUG bevy_mod_scripting_core::script_system: Found a system with name "<Enable the debug feature to see the name>"
at crates/bevy_mod_scripting_core/src/script_system.rs:173 to be clear
so I guess that was it? it worked after enabling the debug feature
although for some reason it can't find the Update schedule
but sure enough I got a bunch of prints from lua after setting it to PostUpdate
oh and it doesn't ever run if I set to Startup or PostStartup, I guess it's too late at that point?
even though I'm not calling it from the callback anymore
Ohh
That sounds right
Damn, that must have started happening last bevy update
Ill have a look at fixing tonight
Hey, I'm using luajit and am noticing that the performance is really bad. Is this expected? I'm gonna try changing to a different Lua version in a bit and I'll report back.
local N = 10000
-- 1) Perf.noop() calls: 9.61ms
for i = 1, N do
Perf.noop()
end
-- 2) Pure Lua empty loop: 9.294ms
local x = 0
for i = 1, N do
x = x + 1
end
LuaJIT seems to be setup:
LuaJIT 2.1.ROLLING โ JIT ON, arch=arm64, os=OSX
JIT flags: fold cse dce fwd dse narrow loop abc sink fuse
Changing to Lua54 seems to have fixed the issue.
-- 1) Perf.noop() calls: 0.301ms
-- 2) Pure Lua empty loop: 0.059ms
This should fix this: https://github.com/makspll/bevy_mod_scripting/pull/531
what's Perf.noop() in this case? a binding ?
that big of a difference happening even in pure lua code is strange
what happens if you increase the N value to something like 1e7 ?
Perf.noop was a noop rust binding
As far as I remember it scaled linearly
I did more debugging, and it seemed like the JIT compiler was failing all traces. I've unfortunately moved on and don't really remember the specifics
first impression ๐
TRACE bevy_mod_scripting_lua: ~/.local/share/cargo/git/checkouts/bevy_mod_scripting-5f706eeba1b2b94f/f6ac743/crates/languages/bevy_mod_scripting_lua/src/lib.rs:345: Context EntityScript(entity: 24v0, script: path scripts/main.lua) is not subscribed to callback Enablethedebugfeaturetoseethename
and my registered PostUpdate system doesn't run
BUT
I'm trying to figure out why enabling the debug feature actually makes it work
it seems the actual error that causes this comes from mlua?
FromLuaConversionError { from: "nil", to: "function", message: None }
oh nvm it's probably trying to find a function called "Enablethedebugfeaturetoseethename" in the script's globals
yep hilarious
function Enablethedebugfeaturetoseethename(time)
print(string.format("[SCRYPT SYSTEM] update system ran, dt=%f", time.delta_secs))
end
oh did I miss a reference to the system name somewhere
ah yeah one sec
yeah basically, bevy doesn't really expose the SystemKey easilly in this area, the callback name it uses is based on the name of the system, which was using DebugName.. not a fan of that struct being such a footgun!
anyhow should be fixed now
yeap, working beautifully
I think there may be some other semi-random inconsistencies, maybe I missed a feature flag or something?
like, for some reason I'm now able to add the system to regular ol Update, but no longer to FixedUpdate
I can get types["ButtonInput<GamepadButton>"], but not types["ButtonInput<KeyCode>"]
This is unrelated, ButtonInput<KeyCode> is not registered against the type registry
As for schedules, this will depend on where youre adding the system, like you cant add systems to FixedUpdate if you are currently running in FixedUpdate
Things have progressed.
After lua actions, scenarios, I now have selection based lua actions:
Is there a way to make lua error panic instead of a warning in the logs? I was thinking of using that for testing purposes.
I think that can be controlled via: https://docs.rs/mlua/latest/mlua/struct.LuaOptions.html
Controls Lua interpreter behavior such as Rust panics handling.
Ah i'll look into that!
@old trail That MR you just did is a godsend ahahaha
I was getting back into some save/loading stuff and fighting with timing again...
Nice! Theres at least one more coming related to the pipeline
I am discovering stuff as i am building my proof of concept
Turns out using the thing yourself gives you perspective haha
Oh, you've been working on your demo game thing?
Auto loading lua scenarios script on launch using command lines (I'll need that for dedicated servers and other things later)
I'll have to pull it again at some point to see how things are shaping up.
Well, I just did and now I need to create those lad files and definitions....
There's not much going on atm but slowly building up a modding framework
I am curious what people think about ScriptComponent how does the fact that it stores multiple scripts in a list play with the ECS for you ? I was considering re-thinking that and having each script live in a child entity of the target entity, to play nicer with change detection
So, because i only use master scripts, i.e, scenarios, game master actions, selection actions. I have not yet attached a single script to an entity.
However, as part of my reflections of running multiple scenarios at the same time (including duplicates), I think I will consider attaching duplicate scenario scripts as a hierarchy of entities.
We both are ahaha
I am planning in inspiring myself from the factorio modding scene for structure, distribution and version control.
Also, i think the current implementation still allows end users to have child entities if your change detection is important no?
Yeah their framework looks real nice
yeah, it does I guess though if people aren't really using the multiple scripts on one entity approach, then only allowing one per component will likely simplify a lot of things internally
Is it worth sepending the effort breaking things down to simplify the internals? It might affect someone who is using BMS who won't see this go by.
Or the question might be, is it expensive to maintain it in that way now that it's set up?
Maybe pinging some user of this channel that haven't talked in a while might be worth it?
I am mostly just curious if people generally use the vec or create children entities etc, not doing anything with it at the moment, but generally BMS is already massive so any simplifications are always good
Hmm, I want to use the multiple script handles, and I've added PRs to ensure that they're loaded in the order they're given, so that's definitely something I'd want to preserve; however, despite me wanting to do this, when I've tried it, it hasn't worked on whim, so I've fell back on my old concatenation code. I'm sure with some effort I could make it work, but last time I was in the midst of a gamejam, so it wasn' t the right time to try.
Thanks for the input! That helps!
I've noticed that in 0.19, global functions and generic types don't get translated into the lua declaration file. I can understand the generic one, but why are the functions ignored?
I don't think generics are supported in general, in part due to missing information in reflection: https://github.com/bevyengine/bevy/issues/17117
I think they are also experimental in LLS
Writing my own game is giving me a lot of ideas, one thing I am noticing is that performance seems to be splendid so far. For example currently I am spawning a static script per spell type in the game, and that spell receives events like on_spell_spawned(entity) on_spell_collision(entity, otherEntity), and with that setup, I was able to spawn hundreds of fully physics simulated projectiles with lua running on those hooks, setting sprites, emitting sounds etc, and the framerate was not getting hit.
Now I am not sure how a VM per spell will scale, but there is always the possibility of sharing contexts between those and using stored callbacks instead.
I am thinking about expanding event callbacks to support more pipelining style workflows, for example on_player_input might benefit from explicit ordering between scripts as well as the option to stop further scripts from processing the callback based on return value
I think it might be easy to start tanking the frame rate if you start running things per update across many entities with non trivial amounts of ECS interaction. Although I don't know where that limit is
I would tend to run things on a message or a event to limit execution ? Or does all script run always every frame ?
Nah scripts purely execute if you send a message + on attach detach
Makes sense !
So you would add more native conditional triggers ?
kinda yeah, for example CallbackLabel might also specify some settings, like ExplicitOrderingEnabled , and ScriptCallbackEvent might have priority set on it, and that way for some callbacks all events will be sorted first. On top of that you could have escape hatches, maybe something like world.stop_processing_attachment(), or just a special return value, that tells the engine to stop handling any more events, either for the specific attachment or say for all events containing an entity etc.
that way you could say build a player controller, with default ordering priority, and then modders could insert something with higher priority and say modify either the payload itself or some state prior to it reaching your controller, or straight up fully override it
I haven't played with that part of the library much so far.
But it does make me think of what they do in BEI
Maybe a BEI based example would avoid developing a whole section of library ?
what's BEI ?
bevy_enhanced_input crate https://discord.com/channels/691052431525675048/1297361733886677036
Ah I see
I am adding more derive macros, and generally cleaning those up, as well as adding an example for custom conversions: https://github.com/makspll/bevy_mod_scripting/pull/538
this year is the year of ergonomics
Thoughts on making ScriptCallbackResponseEvent observable ?
Oh yes please!
Is there still a scriptcallbackresponse when the function is void?
For me this would be useful when saving:
- I ask lua to send me the script values that I need to save
- I then the save lua calls a rust function that indicates it's finished
- Then I can write to file.
Having script end event would allow me to not have all this mechanism anymore.
It's a bit the same for load:
- I send the save data to lua
- I need to wait until it has been executed
- I can then resume game
Ha... Going through your stuff I just realise I can already expose the event...
@old trail Any chance to see some kind of a demo of arcane_assembly at some point? ๐
Is there still a scriptcallbackresponse when the function is void?
Yeah, you configure if the response exists per callback event, but whatever ScriptValue is returned will be present on the response
@Gedes Any chance to see some kind of a demo of arcane_assembly at some point? ๐
Aye would love to, atm there is not that much going on, although it's probably enough to showcase a basic modding setup:
- Mods get a top level script, either attached to the player or as a static script
- Spell components all share a context, and use registered callbacks to listen to events like
on_caston_expire - Spells are parsed from dotgraphs into a DFS graph the spell executor runs in that order
I've got a small bevy_hanabi particle binding layer as well which is pretty neat:
Particle PR: https://github.com/makspll/arcane_assembly/pull/18
Sweet.
Wow.
I've been fighting with some flaky tests loading scripts in my environment for a while and i'm now trying to tackle them to get my code coverage up.
Run time never fails and always load all 3 scripts correctly.
However in test sometimes I load 0, 1 or 2 of my files depending on my PC's mood despite running app.update() a whole bunch.
Would you have an idea why this would fail sometimes? I read the files correctly, I get the correct relative path, but then my scripts do not get attached. Or they don't run? Unsure.
/// Resource tracking all loaded scripts
#[derive(Debug, Resource, Default)]
pub struct LoadedScripts(pub Vec<Handle<ScriptAsset>>);
/// Initial setup
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut loaded_scripts: ResMut<LoadedScripts>,
) {
let script_dir = Path::new("assets/lua/GMActions");
let entries = fs::read_dir(script_dir).unwrap();
for entry in entries.flatten() {
let path = entry.path();
// Accept only `.lua` and `.luau` files
if let Some(ext) = path.extension().and_then(|e| e.to_str())
&& (ext == "lua" || ext == "luau")
&& let Some(relative_path) = path.strip_prefix("assets").ok().and_then(|p| p.to_str())
{
let relative_path = relative_path.to_string();
let handle = asset_server.load(relative_path);
loaded_scripts.0.push(handle.clone());
commands.queue(AttachScript::<LuaScriptingPlugin>::new(
ScriptAttachment::StaticScript(handle),
));
}
}
}
I suspect that something is up with these lines when in a test configuration and/or bevy's asset server.
let handle = asset_server.load(relative_path);
loaded_scripts.0.push(handle.clone());
commands.queue(AttachScript::<LuaScriptingPlugin>::new(
ScriptAttachment::StaticScript(handle),
));
Somehow the script I attach are not run, only sometimes. It's very odd...
Hmm, can you see if theres any clues if you run with trace log level for bms core?
In this example my polygon GM action is never executed for instance.
That file looks like this:
local Template = require("./../library/spawnTemplate")
local simple = require("./../templates/FirstTemplates")
local Types = require("./../library/GMActions")
type GMActionPoints = Types.GMActionPoints
local gm_action_name = "polygon"
register_gm_action(gm_action_name, "Polygon", false, "Digit3")
function on_gm_action(name: string, template: string, data: GMActionPoints, scroll_value: number)
-- do stuff
end
Normally register_gm_action is called and therefore bevy knows about the polygon game master action. And that always runs flawlessly during runtime.
How do you trigger thay callback?
This luau code runs, execute register_gm_action which is a function I registered.
In the log file, it works for the singleEntity and random game master actions which have the same format. However it's not reliable
Sometimes all of the luau files will be executed, sometimes none, somtimes a few.
But perhaps my structure is not great and I need to rework it...
I can see its running in the logs:
01T20:05:12.480896Z TRACE bevy_mod_scripting_lua: Context StaticScript(script: path lua/GMActions/polygon.luau) is not subscribed to callback on_script_loaded
Hmm
If you add a print do you see it?
Here is an example success with the test print in it:
Here is another example of failure where the print did not occur
The print itself is print("TEST_PRINT")
And I have a override to make it print in bevy.
(I tried removing the override also and i have the same results)
One thing that I am suspecting is that maybe something is missing in my bevy test setup that messes with BMS?
Are you potentially queuing callbacks in the same frame youre attaching scripts or is this purely relying on the on load code?
I have two different category of static scripts:
- Gm actions will load and stay loaded, they are never called by bevy in any way before the failure they are just run.
- Scenario will load, wait X amount of frames for the load to complete and then unload.
In the case they successfully load and execute the register functions, I then start sending them callback through bevy.
For the gm actions, I do not send anything to them until the test runs (it always succeeds once the load is successful).
For the scenario i shouldn't either. I do send fixed updates when they are running.
There we go, networked lua script actions using remote procedure calls.
Hi folks !
Really enjoying bevy_mod_scripting so far ! Have been able to figure out & solve most issues so far , except this one :
How can values insideOption<>s / Results be retrieved inside Lua scripts ?
Specifically: I have this component
#[derive(Clone, Default, Component, Reflect)]
pub(crate) struct TemperatureSensor {
pub(crate) temperature: Option<f32>,
}
I can see that the value is displayed as TemperatureSensor { temperature: Some(-270.0) } inside lua scripts, but I need to actually get the value itself.
Thanks in advance !