Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upDynamic Systems and Components #623
Conversation
| if let Some(component_registration) = | ||
| component_registry.get(&match type_info.id() { | ||
| bevy_ecs::ComponentId::RustTypeId(id) => id, | ||
| _ => todo!("Handle external ids in component registry"), |
zicklag
Oct 4, 2020
Author
Contributor
This may need to be fixed before merging. We have to find out how we want to manage the scene registry when it comes to external types. I don't have a full understanding of how it works currently so I didn't implement anything yet
I think I'm going to prioritize figuring out the dynamic component and systems approach before I try to fix this.
This may need to be fixed before merging. We have to find out how we want to manage the scene registry when it comes to external types. I don't have a full understanding of how it works currently so I didn't implement anything yet
I think I'm going to prioritize figuring out the dynamic component and systems approach before I try to fix this.
|
Just an FYI, @cart probably don't waste time reviewing this yet ( even if you get time ) as I found some stuff that might need to change a little as I keep going. I'll mark the PR as not a draft when it's ready for review. |
d6c3844
to
7e44b37
f4ca66f
to
d9e07fb
|
OK, this is still probably a little rough around the edges, but I think the concept is laid out enough to get some review by anybody who is able to look at this. If any community members want to comment on this it'd be good to get as much feedback as possible before Carter has a chance to look at him to save him some time if there are glaring issues. |
1f901da
to
3dccbc9
|
Hey, CI is passing now. :) I just ran my new benchmarks on this PR and the result is ( PR in blue, master in red ): The frame time and the CPU cycles differences are within the noise noise range on my machine ( my laptop with a web browser running on it ), but the CPU instructions are always stable pretty much within 0.01% when there are no changes so this PR clearly represents an increase of at least 1.85% increase in CPU instructions for the benchmark games. I was hoping to avoid slowing down non-scripted games, such as the current benchmark games, at all, but it looks like the new design has a slight overhead. Not sure, how much that means though. |
a362d2e
to
c4b591e
|
I've now successfully demonstrated both dynamic systems and dynamic_components summing up, I think, all that is necessary to allow 3rd party implementations of scripting systems for Bevy! The examples demonstrating both dynamic systems and dynamic components are very limited in scope and do not prove that there aren't bugs when doing queries over multiple archetypes or all kinds of other variables, but for the most part I've built on the existing Bevy logic wherever possible and there is as little new logic as possible, which should help for review and stability. I'm going to start working on a language agnostic scripting system on top of these new features. This will stay separate from Bevy, but it will help stress test these new features once I get it going. |
|
Awesome work! I'm curious to hear what @Ralith would think about upstreaming these changes. |
|
I'm open to the idea, though I'd need to do a proper review. The usecase is well-justified. A few initial thoughts:
Could this be folded into
Maybe a custom |
Oh, that's perfect. I had missed the
That's a good idea, I'll try that out. I'll will add that I'm pretty sure that with these changes the ECS bench iteration speed is not decreased when using static systems. As far as the iteration speed of dynamic systems ( or, probably more accurately, stateful queries ), the last I tried the ECS bench with a dynamic system the iteration speed when from ~1µs to ~100µ compared to the non-dynamic version. I'm not sure how accurate that benchmark was, though. At this point I figured that we can be reasonably sure that we haven't lost a, so far, noticeable amount of performance for non-scripted systems. If we notice scripted systems, or stateful queries or something are slow, we can try to optimize it later after it is actually working, being that the non-dynamic features already there don't appear slower because of the new features. |
|
Using a custom hash implementation and benchmarking just the hash with criterion yields a small performance increase:
Does this look right for a hash implementation? I'm not sure if there is a better way to do this that avoids the #[derive(Debug, Clone)]
pub enum ComponentId {
RustTypeId(std::any::TypeId),
ExternalId(u64),
}
impl Hash for ComponentId {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
ComponentId::RustTypeId(id) => {
id.hash(state);
state.write_u8(0);
}
ComponentId::ExternalId(id) => {
state.write_u64(*id);
state.write_u8(1);
}
}
}
}Edit: Opened a forum topic just to get more feedback. Also it doesn't effect the CPU instructions measurement noticeably for the asteroids and breakout benchmarks. |
|
OK, I got help on the forum that said that the hashes are allowed to collide, so we can totally get rid of any discriminant between impl Hash for ComponentId {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
ComponentId::RustTypeId(id) => {
id.hash(state);
}
ComponentId::ExternalId(id) => {
state.write_u64(*id);
}
}
}
}
Hey that also brings down the CPU instructions a little bit in the game benchmarks. Still a little higher, but not as much as before. |
ecd08b7
to
a383a18
4725ace
to
d8ea798
|
OK, I've gotten this updated with the latest Bevy changes. ( I've still got cleanup to do ) I switched back to making |
bb0ed18
to
09d2e0f
This replaces the use of TypeId for identifying components and instead uses ComponentId which is an enum that can represent either a Rust TypeId or an external id represented by a u64.
311b639
to
07a44c0
07a44c0
to
9111e06
|
OK, I did the cleanup I needed to do and went over the code one more time and I think it's ready for review, now. |
68e588f
to
40a70b4


Related to: #32
Resolves: #142
This PR will attempt to establish the ability to create systems and components that have been determined at runtime instead of compile time. I'm going to try to implement this in one PR because I won't be sure about the sufficiency of the design until I actually get a working example of a dynamically registered system and component ( which I will include with this PR ).
I'm going to try to attack this problem one step at a time:
Steps
Non-Rust Component Ids
Status: Completed in commit: "Implement Custom Component Ids"
Currently bevy_hecs uses
std::any::TypeIdto uniquely identify the component IDs, but this does not allow us to define components that have a non-Rust origin. The first commit in the PR has migrated all of the internals of the bevy ECS to use a newComponentIdinstead that is defined as:Establish Dynamic Queries
Status: Completed in commit: "Implement Dynamic Systems"
This adds a new state type parameter to the
Fetchtrait. This allows compile-time constructed queries like to be constructed withState = ()and runtime constructed queries with the state parameter set to aDynamicComponentQuery.Establish Dynamic Component Insertion
Status: Completed in commit: "Add Dynamic Component Support"
This adds a new implementation of the
Bundletrait,RuntimeBundlewhich can be used to insert untyped components at runtime by providing a buffer of bytes and the required type information.Create Examples
Status: Completed in respective commits
We also have new examples for dynamic_systems and dynamic_components.
Remaining Work
The biggest thing necessary at this point is a solid review. There's a lot of code changed, but thankfully not a ton of new logic. The bulk of the changes are repetitive changes required to add the necessary type parameters and such for the new
Fetch`State type parameter.Otherwise, there are a couple of
todo!()'s inbevy_scenebecause I don't know enough about the Bevy scene architecture to integrate scenes with external components yet. I think that could reasonably be left to a separate PR, but I'm fine either way.