-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace entity spawning abstraction #231
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pattern looks good, i can look for nits tomorrow if this is still up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unhappy about the definition site of the construction functions, as I think this kind of function will be very surprising to a newcomer. The solution probably lies in finding a good naming convention, but I can't think of one.
src/spawn.rs
Outdated
fn spawn_with<M: 'static>(&mut self, command: impl EntityCommand<M>) -> EntityCommands; | ||
|
||
/// Spawn an entity with a [`System`] that receives the new entity ID via [`In<Entity>`]. | ||
fn spawn_fn<M>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The distinction between spawn_with
and spawn_fn
is currently probably impossible to grasp from the naming alone. I suggest renaming this to insert_with
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These both spawn a new entity, though. The difference is whether we're passing in data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, you're right. Can a system implement EntityCommand
so that we can remove this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the orphan rule, that would have to be done upstream. But it would be nice if so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. We still need a better name though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, in this case you can bypass the orphan rule by wrapping the system in a struct and then implementing traits on that struct. Not an option for the template because that is severe type magic, but just wanted to let you know.
src/screens/playing.rs
Outdated
fn playing_screen(In(id): In<Entity>, mut commands: Commands) { | ||
commands | ||
.entity(id) | ||
.add_fn(widget::ui_root) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems very confusing from a first glance when one should use add_fn
and when spawn_fn
. If this is confusing to me as a reviewer, I imagine it would be really really confusing to a newcomer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An explanation in the design patterns doc should mitigate that a bit, but I'm open to bikeshedding.
@alice-i-cecile could you also take a look at this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like this, especially in learning material. There's a ton of complexity and type magic here, and it makes simple tasks appear esoteric and difficult. Boilerplate is better than complexity for this.
I understand the desire to improve things here, but I would be strongly opposed to endorsing code with these patterns as official learning materials.
@alice-i-cecile I've though about this for half a day now and I'm tending the same way. I feel a bit bad since we both gave a thumbs-up for it in #223, but seeing it in practice is just too "scary". I've been thinking about ways to improve the design and make it more approachable, but I'm really struggling with that. My feelings are a less negative than yours since I think the actual user-land code here is quite elegant while still staying flexible, but it is formulated in a foreign design language. As such, I also cannot recommend it for the template. Things would be way easier to accept if
In either case, the implementation would be hidden, which would be a big plus. For the moment, I'd instead go for the simpler route of replacing observers with custom commands. |
Custom commands means having to extract system parameters from |
I don't like extracting stuff manually from My main issues are more:
As for |
For the record, custom commands still requires |
@benfrankel I think that could work, in terms of not introducing too many new abstractions / concepts. In the worst case we can still use the crappy variant that does not return an |
169aad0
to
7714a81
Compare
Done. The tradeoff is not worth losing usability in a real game IMO but it's w/e. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this version is way clearer for an outsider. Other than some minor issues I noted, I'd merge this.
But I also want to hear @alice-i-cecile's opinion again, as this is controversial enough imo.
I want to stress that because the underlying spawning API is missing from Bevy, we will either have a somewhat complex, but decently usable pattern, or a very simple pattern that will break down when the user experiments with it.
I think this PR strikes a good balance now. I'd prefer to ship some way of spawning stuff while returning Entity
or EntityCommands
or similar as, in contrast to many other tradeoffs of the template, this is not something where a user can just switch to a popular community plugin when they are running into trouble.
// to animate our player character. You can learn more about texture atlases in | ||
// this example: https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs | ||
/// Construct a player entity. | ||
pub fn player(id: Entity, world: &mut World) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we rename these to construct_player
and construct_level
now? Seeing as the underlying pattern has shifted.
children.spawn_with(construct_player);
sounds completely reasonable to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think that's more confusing (verbosity aside). The underlying pattern hasn't shifted at all, I just removed support for using a regular system instead of an exclusive system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are at an impasse with the naming here. Requesting a third opinion from anyone, I'll gladly accept the majority vote.
// can specify which section of the image we want to see. We will use this | ||
// to animate our player character. You can learn more about texture atlases in | ||
// this example: https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs | ||
/// Construct a player entity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Construct a player entity. | |
/// Construct a player entity by inserting the relevant components. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could spawn children / do other things as well. Think health bar, nametag, multiple sprite children, colliders, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to guide users more on what "construct" means in this context and why there is a Entity
as a parameter.
/// Construct a level entity. | ||
pub fn level(id: Entity, world: &mut World) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as for fn player
src/ui/widget.rs
Outdated
} | ||
|
||
/// Construct a UI node that fills the window and centers its children. | ||
pub fn ui_root(id: Entity, world: &mut World) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as fn player
Co-authored-by: Jan Hohenheim <[email protected]>
Co-authored-by: Jan Hohenheim <[email protected]>
Co-authored-by: Jan Hohenheim <[email protected]>
|
||
/// An extension trait to support spawning an entity from an [`EntityCommand`]. | ||
pub trait SpawnExt { | ||
// Workaround for <https://github.com/bevyengine/bevy/issues/14231#issuecomment-2216321086>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this should just be fixed upstream.
I think this is an improvement, but I'm still not happy with the level of abstraction / ad-hoc tools here. I think this should be merged, but the linked bug / limitation should be fixed upstream (ping me for reviews!), and I'm still reluctant to officially recommend this template until this is substantially simpler. If you feel that the limitations of just doing things the dumb way are unacceptable, I'm fine to hold off on endorsing this until the BSN work is shipped. |
Closing this for now. Sorry again for the whole work that is not merged. Let's revisit this after some improvements have been implemented upstream. |
All good, it was mostly copy/paste and some mechanical refactoring. |
Fixes #223.
Part of #203.
Will need to update the design doc as well.