Idiomatic way to compose/substitute plugins inputs and outputs #9732
Replies: 3 comments
-
Hello, I think that there are a few different things here that are worth discussing:
On the broader architectural point, Bevy allows for both side-effect-heavy and side-effect-light plugins, as well as for plugins with varying levels of customizability/setup variation. This is actually by design - sometimes you need a plugin that just does the thing for you, and sometimes you need something that provides you with more direct control. To give some examples here:
Each of these plugins have a different purpose, and as a result the degree to which they just do their thing versus let you adjust it changes. Something like a physics system is often very "turnkey" - i.e. you would generally only adjust a few settings if you use an off-the-shelf solution, which is why it doesn't expose a lot of customization there. On the other hand, something like an AI system is not going to be used the same way in most games, so it needs to be built to be versatile. I hope this all makes sense? Do you have any additional questions here? |
Beta Was this translation helpful? Give feedback.
-
With an ECS each scheduled system should be its own independent black box. However, as such it is important that these black boxes be written in a way that they play nicely with others, which in this case sounds like it didn’t happen. To do so it’s important that every plugin provide marker components and restrict its operations to entities which have said marker components. That way you can safely add and experiment with a new plugin without risking breaking everything in your application. In the camera example you mentioned I’d want some form of physics marker component that only exists on entities which can can be handled by the physics engine. This means the camera should not have a physics component. Another option might be to write your own system code and call it in place of the plug-in’s system code, though if that is your only option I’d contact the author and ask why they aren’t utilizing markers of some kind or move to another crate. The reason I say this is the amount of extra work you’ll be adding on to your plate to keep things working if the crate maintainer doesn’t understand the importance of this as they’ll like introduce additional unexpected side effects in the future. |
Beta Was this translation helpful? Give feedback.
-
Thank you @lee-orr and @cwalter5 , your answers just suit to how I finally figured out the thing : plugin authors write their plugins the way they want, and there is no general perfect solution to circumvent their eventually unwanted interactions with our app code ; I'd like to have your opinions but I think we could agree that Bevy should incorporate some scalable way for the host app developer to "virtualize" the components such that there is less chance that we throw up integrating a plugin because the way it was developed does not suit our dataflow and logic well. @lee-orr mentioned a "sub-app" but I've not come down to this concept in Bevy and I don't know how it may bring a solution to those "component conflicts". Does it bring performance overhead in some way ? Does the "extract" phase always involves a hard memory copy ? Both of those techniques seem to involve temporarily doubling memory use and copying much data (In my case I have just one camera but suppose I have the same problem with thousands of entities, and then with more than two plugins over the same set of components...). Going to a more low-level perspective (unless the Rust compiler can optimize away those memory writes), I think the app may suffer from (avoidable) memory overhead if a lot of plugin data conflict with other data. If Bevy had brought up a way to functionally substitute the way a plugin writes its output by custom logic, maybe those memory writes serving as "plugin output extraction" could be replaced by simple function calls. The function applies some needed logic to transform the data in a way that makes it not conflicting with other plugins anymore, then data just has to be read by other plugins. Since plugin data are in CPU cache and/or registers at the moment the plugin sends its output to target components, there is high chance that this solution diminish the number of slower memory writes, but this involves changing how "components" are represented in Bevy ; at least in plugins, they would become callable dynamic traits rather than pure data, and this may contradict the current ECS vision. I'm a beginner to Bevy so maybe my ideas are too naive or constitute immature optimizations. Feel free to discuss those ideas though at this stage I think this topic may be moved to "Discussion" (should I do it myself?) instead. Again, thanks for your answers. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello. I am new to Bevy and I'm currently studying the architecture, the way of doing things. Fully thinking in terms of ECS is not something easy at start but we can see the easy parallelism that it offers. This uniform way of doing computations is making modularity possible since we just have to split different concerns in plugins and plug them at the application start. Plugins register their systems (and maybe their components) and that's it. It makes the import of third party features easy and uniform.
However, I'm struggling at understanding what is the normal way to integrate different features that come from different plugins, when said plugins conflict at each other, I mean when one plugin, in the context of my app, is wrongly writing to a component used by another plugin.
I can give an exemple of this problem :
Transform
component of entities also possessing theFlyCam
component.LinearVelocity
,AngularVelocity
and others that serve both as input and output (but the final output is of course the Transform component) . For the physics computation to stay realistic on all objects having a physical existence (=> objects having a Transform component) I must not write on the Transform component directly but let the physics plugin handle it alone.The problem arises when I want my FPS camera to be a physical object. I mean that going forward must be a physical event (increasing LinearVelocity) that could be eventually blocked by the physics system (object collisions). But as the camera plugin directly writes to the Transform component, my character pass through objects.
In the current state of things the only solution I see would be to plug a system that saves the
Transform
before the camera system runs, then another system gets the delta, restore the old Transform component, and use the delta to feed the physics system (LinearVelocity and AngularVelocity). This seems to be an extremely ugly way of solving my problem.I am asking if I am doing something wrong in my will to integrate those two systems, or if the plugins themselves were wrongly written (at least for modularity/integration). I am not aware of an idiomatic way to control the integration of plugins with each other.
In the current Bevy architecture, it seems that plugins are "white boxes" rather than black boxes: all of their effects can be considered "side effects" since components are common to all plugins. I see no way to substitute a component by another in the eyes of a plugin.
What I would like to do is to prevent the camera plugin from writing on the generic Transform component. Instead I would like to see plugins as black boxes without side effects (as far as possible), with the responsibility to feed them with inputs and take outputs being mine. I would benefit from the logic of the camera plugin, but I would handle the output data myself. This way I would be free to use the camera "output" to modify the physical components, thus correctly integrating the camera logic with the physics logic.
I have some ideas to give Bevy the possibility to seal/segregate plugins inputs/outputs, but I won't develop further on that for now seems I may just be missing something here.
Beta Was this translation helpful? Give feedback.
All reactions