specs
specs copied to clipboard
FlaggedStorage with information about the change in value.
Description
Update flagged storage, or create a new storage, so that the ComponentEvent contains information about the component before and after the change.
- Insert contains a copy of the value inserted
- Modified has before and after
- Removed has the value after it was removed.
Motivation
I maintain collision detection information in a resource. This needs to be kept in sync with the entities in specs.
When an entity is deleted, I need to find the handle stored on the component to identify the object in the collision information. This handle can be used to delete it from the collision world. Since the entity has already been deleted, I can't look up this information from the world.
Right now, whenever I delete an entity, I just check if it has the information and delete the collision object. This is less than ideal, since I must change every system to account for my collision detection system.
Drawbacks
- Is it a breaking change? If we make a new storage for this, no. If we modify FlaggedStorage, then yes.
- Can it impact performance, learnability, etc? No, using and learning about this is optional. Changes should not affect performance of anything else.
Unresolved questions
So you're have separate handle for physics object? Can't you just use index of an entity?
In this case, it looks like I can't. I'm using ncollide2d, which has its own handle object. When you add an object to CollisionWorld
, you get a handle to the object in the world, and a mutable reference to the object. (CollisionObjectSlabHandle, &mut CollisionObject<N, T>)
.
I don't think I can influence the handle to relate it to the entity id.
One other thing I've tried: You can store information on the object, for example the entity index. You can then iterate over all the objects to get the handle and remove it. But this is O(n)
, and I haven't found a faster way.
You could have map from entity index to collision handle then.
True, but the drawback to this approach is that it requires more code to determine when an entity is deleted to free space on the index. If it is a component, this is done by specs. Is there a way to join over the map? There are a few systems that use the component in a join, and it would be nice to still have that.
I did a bit of development on this. You can implement this outside of the specs crate, making a new struct similar to FlaggedStorage.
At this point, my use case is covered. The question that I have left is: Is this something that we should put in this library to share, or should we leave it to other libraries/code?
Regarding the question in the last comment, thought I would chime in and say I would also get a lot of use out of this feature were it in specs.
@blargg this would be a very useful feature. I can think of the following use cases :
- Syncing separate data structures stored in ressources (such as your example). There are many uses cases similar to this.
- Differential history (for example to implement state diffing for incremental saving on a server, or to implement undo/redo mechanism). I was thinking of building something similar, would you be willing to share your solution ?