Directly run system given world#2427
Directly run system given world#2427alice-i-cecile wants to merge 18 commits intobevyengine:mainfrom
Conversation
| fn run(&mut self, world: &mut World); | ||
|
|
||
| /// Runs the exclusive system directly on the world, initializing the world correctly | ||
| /// |
There was a problem hiding this comment.
For both methods, it may be useful to describe how to persistently store and then access a system, rather than initializing it every frame.
This reduces work by enabling query caching and also allows Local resources to persist correctly.
I'm just not sure that the API docs are the right place to put that; it feels like content that might be better suited to the book.
There was a problem hiding this comment.
Actually, I suppose that the way to do this is to probably store the system, run .initialize once, and then call the old .run() manually.
The new method is much more convenient, but will probably perform worse for repeated invocations.
Hmm. Maybe we also demonstrate how to store and run a stage in the same section of the book?
DJMcNab
left a comment
There was a problem hiding this comment.
I'm not convinced that this API is more useful than the existing APIs
I think I'd prefer to just change the run method to initialise self; although this API could be useful for exclusive systems since they might already get called using the 'run' method.
Really, we just need to be much more explicit about System's safety conditions
| /// | ||
| /// Use [`run_direct`] instead if you are manually running a system outside of a schedule | ||
|
|
||
| fn run(&mut self, world: &mut World); |
There was a problem hiding this comment.
Does this imply that run has an additional safety requirement that self is initialised for this world?
If that is so, then it should be unsafe
There was a problem hiding this comment.
It's not unsafe in the Rust sense; it merely panics with an opaque error message.
The problem with this is that you lose all the nice caching, and have to repeat the initialization work repeatedly. This is much less of an issue in one-off systems that are being run than it is in schedules though.
The aim of this is actually to make working with exclusive world access easier, rather than compete directly with the way that other |
|
But I mean that the actual body of this function seems to be: fn apply_direct(world){
self.init(world);
self.run(world);
} |
|
Immediately applying buffers is the other very useful trick for ordinary non-exclusive systems, which lets you bypass thinking about "have my commands applied yet". This is largely a convenience method, but I think that it does a good job helping reduce boilerplate and mental overhead for basic uses by hiding some of the largely internal implementation details and just doing what end users would like to do when writing custom commands or using ordinary system syntax within larger exclusive systems.
|
Credit to @mockersf for teaching me how to do this
error[E0599]: no method named `run_direct` found for struct `ExclusiveSystemFn` in the current scope
|
Closing this out as I don't think it's immediately the way forward. We can easily reimplement this if needed. |
Objective
Systems are an ergonomic and expressive API for performing well-encapsulated complex logic.
However, you could not easily use them while working directly with &mut World for custom commands, exclusive systems, writing tests or bare-bones bevy_ecs usage.
Solution
Adds a System::run_direct method, which immediately executes a single system on a particular world and then flushes any Commands (or similar system parameters).
The equivalent run_direct method is also created for exclusive systems.
This is also very useful for users who may want to construct their own game loop in part or whole, sacrificing parallelism for simplicity and control.
Notes
Successor to #2417; exposing an API that dodges the ownership issues created there. Closely related to #2234.