Scene Components#24008
Conversation
There was a problem hiding this comment.
I like the idea of a SceneComponent and macro but I really don't like making it part of the ECS and feature gating it. To me a component and the ECS is and should not be aware of what a scene is.
In Bevy, components are the "unit of behavior".
Could you elaborate? Why is this in quotes? I was under the impression systems are the behavior in an ECS, operating on the data (components).
Ofc you can encapsulate logic onto components but that's opinionated and not inherently an ECS/Bevy thing the way I see it.
I would heavily recommend solving this through architecture and not using feature flags for this since it introduces circular dependency traps among other annoyances (editors can have all flags, depending on config). Personally I dont think this is what features should be used for and this is clearly a bandaid that affects devex negatively.
TL;DR: I think its a good idea overall but I dont think it belongs in the ecs.
|
I believe this is "ready". I've opted not to implement the "static" enforcement of disallowing |
alice-i-cecile
left a comment
There was a problem hiding this comment.
I really like the improved API and the better separation of concerns. Much better; I'm glad we took the time to get this right.
However, I was promised docs!
/// See the "Scene Components" sections of the [
Scene] docs to see how this is used in practice.
Three complaints here:
- I think this should be in the crate docs: the rest of our high-level explanation and usage context goes here.
- Those docs should go over the relation to required components, at least briefly.
- I think you forgot to actually add those docs :) Checking
Sceneon this branch does not reveal any new docs.
Diddykonga
left a comment
There was a problem hiding this comment.
Excellent 👍
The Component Derive cleanup is nice, still might be able to add Resource as an attribute to the Component derive but that's future work.
NicoZweifel
left a comment
There was a problem hiding this comment.
Thanks for resolving 👍
Trashtalk217
left a comment
There was a problem hiding this comment.
I did a once over for the ECS stuff and it looks good. I like that it's sufficiently well seperated from the Scene stuff.
Attempting to spawn a scene component on its own without the scene (ex: commands.spawn(Player::default())) will log an error, as Scene Components should never exist without their scene.
This is definitely a good usecase for archetype invariants, which we should look into.
Objective
It is essentially a Bevy rite of passage to define a
Playercomponent and then ask "ok when I spawnPlayer, how do I spawn all of the other entities / components / scenes it needs to function with it?".In Bevy, components are the "unit of behavior". The presence of a component indicates that the entity should behave a certain way. Scenes are inextricable from behaviors, yet currently there is no way to tie Components (bevy's unit of behavior) to scenes. This is a fundamental gap in the Bevy data model. It is a problem that developers expect their engine to solve for them.
It is high time that we had an official solution to this problem. BSN was built to be that solution, and it is now time to do the last-mile work to facilitate the
Component <-> ScenerelationshipSolution
It is now possible to define "scene components", where
SceneComponent: Component:This enables inheriting from the Player component as a scene:
After the inherited
Playerscene component is spawned, the entire scene is available. This means that you canQuery<&Player>in your ECS systems, and trust that the entire scene is also present.Inheritance Syntax vs Patch Syntax
Notice that this uses inheritance syntax in BSN (
:), rather than normal "component patch" syntax (ex:bsn! { Player { score: 0 } }. Semantically these are different things:Attempting to spawn a scene component on its own without the scene (ex:
commands.spawn(Player::default())) will log an error, as Scene Components should never exist without their scene.Custom Scene Functions
When deriving
SceneComponent, it defaults to usingSelf::sceneas the "scene function". Scene functions can also be manually specified:Inherit BSN Asset Paths
Alternatively, a scene asset path can be specified:
Once we port the glTF loader to BSN, this will also be supported:
Scene Props
Sometimes it is desirable to "parameterize" a scene: pass in values to the scene which determine what the scene outputs are.
The answer to this in BSN is "scene props":
Notice the
@fieldsyntax, which specifies that a prop is being set instead of a field. Props are evaluated "immediately" at the point of inheritance where the scene is constructed. This means that they are not "patchable".You can set both props and normal fields at the same time:
Scene props can be used with templates:
Scene Components are Template-able
The Scene Component is Always Added
Specifying the scene component manually in the scene function is not necessary. It will be added automatically:
However you can patch the scene component in the scene if you would like. This comes in handy if you would like props to contribute to the scene component's value:
SceneComponent Trait
This is what SceneComponent looks like under the hood:
In general, developers should prefer
#[derive(SceneComponent), which derives this trait automatically, ensures the Component is never spawned without its scene, and automatically initializes theComponenteven if it isn't specified explicitly in the user-defined scene function.Reusable Component Derive Logic
This PR moves the component derive logic into a new
bevy_ecs_macro_logiccrate and refactors it to be reusable and extendable.This enables the
SceneComponentderive to reuse and configure theComponentderive. I also took the liberty of porting the redundantResourcederive logic to this system, as it follows the same pattern.PR Todo
Scene.Whats Next