2:16 PM
If you want to disable a single component, I think the neatest method is to include an enabled/disabled flag on that component, check it, and skip it in your iteration loop.
Or you could consider removing the component (extracting the entity and adding it to another archetype without the excised component), and re-adding it if you later want to re-enable it. That gets trickier if the component has state you want to persist between cases.
Hmmm! Another thing you could try if you have only a few components that need this, is to add a marker component to indicate enabled states. So I have an archetype [Transform, Rotation, Hit] for inactive hits, and when I want to activate one I add a HitEnabled component, moving it to the archetype [Transform, Rotation, Hit, HitEnabled]
But coming back to your question about the piles, you'd keep an _activeCount on each archetype, in addition to _count, and maintain the invariant that the first _activeCount entries in the array are the active ones. Systems that care about active state should iterate over the first _activeCount items, not all _count living items.
When you want to deactivate an entity, you'll likely want to queue a request to do so at the end of the frame, so that entity indices don't move around in the middle of an ongoing operation. Then you swap the newly-deactivated entities' components with the last active entity's components in their respective arrays, and decrement _activeCount.
So the deactivated entity trades its index with an active one (possibly itself). Then you update any book-keeping that references entities so that they still point to the correct indices. To make this work, no other system should be allowed to hold onto an entity by index past the end of a frame, so it has to fetch the updated index next frame to always have the correct location.
@DMGregory Alright, thanks ^^ now i understand what you meant with pile :D i still wanna have that feature in an automatic way.
So i could either use an interface for each component like
IActive
which returns a bool to skip it in the query... or i could store some sort of entity information EntityInfo{ BitVector disabledComponents}
and check that one to skip components in the iteration... or i could wrap all components in another struct which looks like this WrappedComponent<T>{ T component, bool disabled}
. Which one of those ways is probably the smartest and most efficient one ? ^^
2:33 PM
I might call it a Toggleable<T> - it ends up working a bit like a nullable struct. But I still wouldn't apply it to every component type in an archetype - it should be something you request when it's needed and skip when it's not, like new Archetype(typeof(Transform), typeof(Toggleable<BoxCollider>)) for an entity that always has an active transform but has a collider that can turn on/off.
That way you only pay the cost (or have to type the extra toggleable.component) when you want it, and can skip it when it's not relevant.
Hmmm... you could even design your own ToggleableCollection<T> : IList, and have the archetype's components array store ILists that are either T[] or ToggleableCollection<T>s. That would let you give it an iteration method that automatically skips toggled-off items, rather than repeating that check in all systems that iterate the array. Might be more complexity than it's worth though.
Thats even a better idea :D So we only pay the price when we really need it. How would the queries work then ? Lets say we search for something like
Transform, Rotation, Hit. This would exclude
Toggleable<Hit>` i assume, right ? So we need to search explicit for Transform, Rotation, Toggleable<Hit>
? ^^
3:10 PM
3 hours later…
6:16 PM
« first day (4113 days earlier) ← previous day next day → last day (914 days later) »