Fix issues with components and remove components when entities are destroyed
This commit is contained in:
parent
4e438d3ccc
commit
d8d490bff9
|
@ -200,7 +200,6 @@ void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const P
|
|||
linkProxyShapeWithEntity(entity, index);
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
|
||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
|
||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
||||
}
|
||||
|
@ -305,43 +304,6 @@ void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index2 || !hasPreviousProxyShape(index2));
|
||||
}
|
||||
|
||||
// Perform garbage collection to remove unused components
|
||||
void ProxyShapesComponents::garbageCollection(const EntityManager& entityManager) {
|
||||
|
||||
// TODO : Make sure we call this method each frame
|
||||
|
||||
// We use lazy garbage collection. The idea is to pick random components and destroy
|
||||
// them if their corresponding entities have been destroyed. We do this until we hit
|
||||
// GARBAGE_COLLECTION_MAX_VALID_ENTITIES in a row. Therefore, it cost almost nothing
|
||||
// if there are no destroyed entities and it very quickly destroys components where there
|
||||
// are a lot of destroyed entities.
|
||||
|
||||
uint32 nbHitValidEntitiesInARow = 0;
|
||||
|
||||
// For random number generation
|
||||
std::random_device rd;
|
||||
std::mt19937 eng(rd());
|
||||
|
||||
while (mNbComponents > 0 && nbHitValidEntitiesInARow < GARBAGE_COLLECTION_MAX_VALID_ENTITIES) {
|
||||
|
||||
// Select a random index in the components array
|
||||
std::uniform_int_distribution<uint32> distr(0, mNbComponents - 1);
|
||||
uint32 i = distr(eng);
|
||||
|
||||
// If the corresponding entity is valid
|
||||
if (entityManager.isValid(mEntities[i])) {
|
||||
nbHitValidEntitiesInARow++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
nbHitValidEntitiesInARow = 0;
|
||||
|
||||
// Destroy the component
|
||||
removeComponent(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void ProxyShapesComponents::removeComponent(uint32 index) {
|
||||
|
||||
|
@ -430,12 +392,13 @@ void ProxyShapesComponents::removeComponent(uint32 index) {
|
|||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
|
||||
mSleepingStartIndex--;
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
mNbComponents--;
|
||||
}
|
||||
|
||||
|
@ -454,6 +417,7 @@ bool ProxyShapesComponents::hasNextProxyShape(uint32 index) const {
|
|||
// Destroy a component at a given index
|
||||
void ProxyShapesComponents::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
|
||||
mEntities[index].~Entity();
|
||||
mLocalBounds[index].~AABB();
|
||||
|
@ -500,3 +464,19 @@ void ProxyShapesComponents::setIsEntitySleeping(Entity entity, bool isSleeping)
|
|||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
||||
}
|
||||
|
||||
// Remove all the components of a given entity
|
||||
void ProxyShapesComponents::removeComponents(Entity entity) {
|
||||
|
||||
auto it = mMapEntityToComponentIndex.find(entity);
|
||||
|
||||
// While there are components for this entity
|
||||
while (it != mMapEntityToComponentIndex.end()) {
|
||||
|
||||
// Remove the component
|
||||
removeComponent(it->second);
|
||||
|
||||
it = mMapEntityToComponentIndex.find(entity);
|
||||
}
|
||||
|
||||
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
||||
}
|
||||
|
|
|
@ -169,11 +169,11 @@ class ProxyShapesComponents {
|
|||
/// Add a component
|
||||
void addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component);
|
||||
|
||||
/// Remove all the components of a given entity
|
||||
void removeComponents(Entity entity);
|
||||
|
||||
/// Notify if a given entity is sleeping or not
|
||||
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
||||
|
||||
/// Perform garbage collection to remove unused components
|
||||
void garbageCollection(const EntityManager& entityManager);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -140,45 +140,6 @@ void TransformComponents::addComponent(Entity entity, bool isSleeping, const Tra
|
|||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Perform garbage collection to remove unused components
|
||||
void TransformComponents::garbageCollection(const EntityManager& entityManager) {
|
||||
|
||||
// TODO : Make sure we call this method each frame
|
||||
|
||||
// We use lazy garbage collection. The idea is to pick random components and destroy
|
||||
// them if their corresponding entities have been destroyed. We do this until we hit
|
||||
// GARBAGE_COLLECTION_MAX_VALID_ENTITIES in a row. Therefore, it cost almost nothing
|
||||
// if there are no destroyed entities and it very quickly destroys components where there
|
||||
// are a lot of destroyed entities.
|
||||
|
||||
uint32 nbHitValidEntitiesInARow = 0;
|
||||
|
||||
// For random number generation
|
||||
std::random_device rd;
|
||||
std::mt19937 eng(rd());
|
||||
|
||||
while (mNbComponents > 0 && nbHitValidEntitiesInARow < GARBAGE_COLLECTION_MAX_VALID_ENTITIES) {
|
||||
|
||||
// Select a random index in the components array
|
||||
std::uniform_int_distribution<uint32> distr(0, mNbComponents - 1);
|
||||
uint32 i = distr(eng);
|
||||
|
||||
// If the corresponding entity is valid
|
||||
if (entityManager.isValid(mEntities[i])) {
|
||||
nbHitValidEntitiesInARow++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
nbHitValidEntitiesInARow = 0;
|
||||
|
||||
// Destroy the component
|
||||
removeComponent(i);
|
||||
}
|
||||
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void TransformComponents::removeComponent(uint32 index) {
|
||||
|
||||
|
@ -214,14 +175,15 @@ void TransformComponents::removeComponent(uint32 index) {
|
|||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
|
||||
mSleepingStartIndex--;
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
mNbComponents--;
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
|
@ -309,8 +271,26 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
// Destroy a component at a given index
|
||||
void TransformComponents::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
assert(mMapEntityToComponentIndex[mEntities[index]] == index);
|
||||
|
||||
mMapEntityToComponentIndex.remove(mEntities[index]);
|
||||
|
||||
mEntities[index].~Entity();
|
||||
mTransforms[index].~Transform();
|
||||
}
|
||||
|
||||
// Remove all the components of a given entity
|
||||
void TransformComponents::removeComponents(Entity entity) {
|
||||
|
||||
auto it = mMapEntityToComponentIndex.find(entity);
|
||||
|
||||
// If there is a component for this entity
|
||||
if (it != mMapEntityToComponentIndex.end()) {
|
||||
|
||||
// Remove the component
|
||||
removeComponent(it->second);
|
||||
}
|
||||
|
||||
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
||||
}
|
||||
|
|
|
@ -105,8 +105,8 @@ class TransformComponents : public Components {
|
|||
/// Add a component
|
||||
void addComponent(Entity entity, bool isSleeping, const TransformComponent& component);
|
||||
|
||||
/// Perform garbage collection to remove unused components
|
||||
void garbageCollection(const EntityManager& entityManager);
|
||||
/// Remove all the components of a given entity
|
||||
void removeComponents(Entity entity);
|
||||
|
||||
/// Return the transform of an entity
|
||||
Transform& getTransform(Entity entity) const;
|
||||
|
|
|
@ -197,8 +197,8 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
|
|||
// Reset the contact manifold list of the body
|
||||
collisionBody->resetContactManifoldsList();
|
||||
|
||||
// Destroy the corresponding entity
|
||||
mEntityManager.destroyEntity(collisionBody->getEntity());
|
||||
// Destroy the entity and its components
|
||||
destroyEntity(collisionBody->getEntity());
|
||||
|
||||
// Call the destructor of the collision body
|
||||
collisionBody->~CollisionBody();
|
||||
|
@ -248,6 +248,19 @@ void CollisionWorld::notifyBodySleeping(Entity entity, bool isSleeping) {
|
|||
mProxyShapesComponents.setIsEntitySleeping(entity, isSleeping);
|
||||
}
|
||||
|
||||
// Destroy an entity and all the associated components
|
||||
void CollisionWorld::destroyEntity(Entity entity) {
|
||||
|
||||
// Destroy the corresponding entity
|
||||
mEntityManager.destroyEntity(entity);
|
||||
|
||||
// TODO : Make sure we notify all the components here ...
|
||||
|
||||
// Notify all the components
|
||||
mTransformComponents.removeComponents(entity);
|
||||
mProxyShapesComponents.removeComponents(entity);
|
||||
}
|
||||
|
||||
// Test if the AABBs of two bodies overlap
|
||||
/**
|
||||
* @param body1 Pointer to the first body to test
|
||||
|
|
|
@ -128,6 +128,9 @@ class CollisionWorld {
|
|||
/// Notify the world if a body is sleeping or not
|
||||
void notifyBodySleeping(Entity entity, bool isSleeping);
|
||||
|
||||
/// Destroy an entity and all the associated components
|
||||
void destroyEntity(Entity entity);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
|
|
@ -479,8 +479,8 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
|
|||
// Reset the contact manifold list of the body
|
||||
rigidBody->resetContactManifoldsList();
|
||||
|
||||
// Destroy the corresponding entity
|
||||
mEntityManager.destroyEntity(rigidBody->getEntity());
|
||||
// Destroy the corresponding entity and its components
|
||||
destroyEntity(rigidBody->getEntity());
|
||||
|
||||
// Call the destructor of the rigid body
|
||||
rigidBody->~RigidBody();
|
||||
|
|
Loading…
Reference in New Issue
Block a user