Skip to content
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

Entity Markers #6556

Open
DasLixou opened this issue Nov 12, 2022 · 20 comments
Open

Entity Markers #6556

DasLixou opened this issue Nov 12, 2022 · 20 comments
Labels
A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use X-Controversial There is active debate or serious implications around merging this PR

Comments

@DasLixou
Copy link
Contributor

What problem does this solve or what need does it fill?

A Marker trait that can mark an entity. example

#[derive(Marker)]
pub enum Players {
    Red,
    Blue,
    Green,
}

then we can assign an entity with a marker

commands.spawn(PlayerBundle::default()).mark(Players::Red);

and we can easily query players

fn add_items_to_red_and_blue(red_query: Query<Player, Or<MarkedAs<Players::Red>>, MarkedAs<Players::Blue>>>) {
    // ...
}

What solution would you like?

An Marker that works like a Resource but holds a EntityID and the Marker can be used in Queries.

What alternative(s) have you considered?

Manually make Resources holding EntityIDs and then using a normal query and using .get with the entityID from the resource.

@DasLixou DasLixou added C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Nov 12, 2022
@harudagondi harudagondi added A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use and removed C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Nov 12, 2022
@DasLixou
Copy link
Contributor Author

This requires enum variants as types, which is not possible in Rust. See:

* [Types for enum variants rust-lang/rfcs#1450](https://github.com/rust-lang/rfcs/pull/1450)

* [Enum variant types rust-lang/rfcs#2593](https://github.com/rust-lang/rfcs/pull/2593)

* [Indexes: look up entities by the value of their components #4513](https://github.com/bevyengine/bevy/issues/4513)

* [Query filter for component value rather than component existence #5639](https://github.com/bevyengine/bevy/issues/5639)

But it works for SystemLabel, and it is infact just a label. the whole entity it corresponds to wouldn't be stored in the marker directly but would be in a lookup table, wouldn't it?

@harudagondi
Copy link
Member

This specific part would not work: MarkedAs<Players::Red>. You cannot use an enum variant as a type.

@DasLixou
Copy link
Contributor Author

This specific part would not work: MarkedAs<Players::Red>. You cannot use an enum variant as a type.

oh! thats pretty sad. But with structs it would work? like

#[derive(Marker)]
pub struct RedPlayer;

?

@ickk
Copy link
Member

ickk commented Nov 12, 2022

You can basically achieve something to the same effect by just using individual "marker components":

#[derive(Component)]
pub struct Red;
#[derive(Component)]
pub struct Blue;
commands.spawn((Player::new(), Red));
fn system(query: Query<Player, With<Red>>) {
    // ...
}

@DasLixou
Copy link
Contributor Author

You can basically achieve something to the same effect by just using individual "marker components":

#[derive(Component)]
pub struct Red;
#[derive(Component)]
pub struct Blue;
commands.spawn((Player::new(), Red));
fn system(query: Query<Player, With<Red>>) {
    // ...
}

Yes but that doesn't have to only resolve into one entity. it can have multiple when you don't do it quite well.. but thats probably a better thing than using a resource

@harudagondi
Copy link
Member

If you need it to resolve it into one entity, why not store that entity in a resource? Like

#[derive(Resource)]
pub struct RedPlayer(Entity);
#[derive(Resource)]
pub struct BluePlayer(Entity);

So that you can guarantee you can have one entity for each color.

@ickk
Copy link
Member

ickk commented Nov 12, 2022

If you need a singleton but don't want to use a Resource, there is also the Query::get_single method, which will give you Result letting you know if there isn't exactly one match for the query. This won't actually guarantee you only have one, but it will at least let you detect/handle when the invariant is violated.

@DasLixou
Copy link
Contributor Author

yeah but both of them are a little bit messy or don't really guarantee that you'll have one. And both of them make it hard for the scheduler to asynchronously handle them because the information that we only want that one specific entity won't be given to the scheduler (at least thats what i thought)

@ickk
Copy link
Member

ickk commented Nov 12, 2022

While that's true in some senses.. a system that only mutably queries for a single entity is unlikely to run for a very long period of time. Plus if you had such a large number of systems in your schedule that you were worried about wasting any CPU time at all.. surely many of those other systems would not need access to the same components and so could run concurrently anyway?

@DasLixou
Copy link
Contributor Author

Well.. thats true.. it's just a feature request because i think its a neat feature i would also like. when you say its not worth it then ok :). but ideas are always good, aren't they?

@ickk
Copy link
Member

ickk commented Nov 12, 2022

certainly :)

@alice-i-cecile
Copy link
Member

Yep, unless and until we get something like enum-variants-as-types, this can't be implemented. Closing this out :)

@alice-i-cecile alice-i-cecile closed this as not planned Won't fix, can't repro, duplicate, stale Nov 12, 2022
@DasLixou
Copy link
Contributor Author

Ok I'm happy to pronounce: I made a working thing for this in 3 hours 🤣. Was very fun to make: https://github.com/ChoppedStudio/bevy_ecs_markers

@alice-i-cecile
Copy link
Member

alice-i-cecile commented Dec 18, 2022

Super cool! What's the algorithmic complexity of this approach?

@DasLixou
Copy link
Contributor Author

Super cool! What's the algorithmic complexity of this approach?

To get from the marker to the Entity, it’s just O(1), but I don’t know how bevy handles Resources and Queries where I pull an Entity 😅

@alice-i-cecile
Copy link
Member

Query.get is O(1), and resources are also a constant time lookup :)

@DasLixou
Copy link
Contributor Author

Query.get is O(1), and resources are also a constant time lookup :)

:O nice to hear 😁

@DasLixou
Copy link
Contributor Author

Yesterday I made some performance and style improvements, it now feels like it would be a normal bevy feature 😂

@alice-i-cecile alice-i-cecile added the S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! label Dec 20, 2022
@DasLixou
Copy link
Contributor Author

Because of EntityNotes issue, I tried to overhaul the prototype implementation, new release out with bevy 0.13 release

@alice-i-cecile alice-i-cecile added X-Controversial There is active debate or serious implications around merging this PR and removed S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! labels Mar 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

No branches or pull requests

4 participants