Skip to main content

GameObjectPoolManager Class

High-level manager for GameObject pooling operations. More...

Declaration

class helios::engine::runtime::pooling::GameObjectPoolManager { ... }

Public Member Typedefs Index

usingEngineRoleTag = helios::engine::common::tags::ManagerRole

Public Member Functions Index

GameObjectPoolManager &addPoolConfig (std::unique_ptr< GameObjectPoolConfig > gameObjectPoolConfig)

Registers a pool configuration for later initialization. More...

helios::engine::runtime::pooling::GameObjectPoolSnapshotpoolSnapshot (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId) const

Returns a snapshot of the pool's current state. More...

std::optional< helios::engine::ecs::GameObject >release (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId, const helios::engine::ecs::EntityHandle &entityHandle)

Releases a GameObject back to its pool. More...

std::optional< helios::engine::ecs::GameObject >acquire (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId)

Acquires an inactive GameObject from the pool. More...

voidinit (helios::engine::runtime::world::GameWorld &gameWorld)

Initializes all registered pools. More...

voidflush (helios::engine::runtime::world::UpdateContext &update_context) noexcept

Manager flush callback (currently unused). More...

GameObjectPool *pool (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId) const

Retrieves a pool by its ID. More...

voidreset ()

Resets all pools by releasing all active GameObjects. More...

voidreset (const types::GameObjectPoolId poolId)

Reset the pool with the specified poolId. More...

Private Member Functions Index

voidfillPool (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId, helios::engine::ecs::GameObject gameObjectPrefab)

Populates a pool with cloned prefab instances and locks it. More...

Private Member Attributes Index

helios::engine::runtime::pooling::GameObjectPoolRegistrypools_ {}

Registry of GameObjectPools for entity recycling. More...

helios::engine::runtime::world::GameWorld *gameWorld_ = nullptr

Non-owning pointer to the associated GameWorld. More...

std::unordered_map< helios::engine::runtime::pooling::types::GameObjectPoolId, std::unique_ptr< GameObjectPoolConfig > >poolConfigs_

Pending pool configurations awaiting initialization. More...

Description

High-level manager for GameObject pooling operations.

GameObjectPoolManager provides a unified interface for managing multiple GameObjectPools. It handles pool configuration, initialization, and the acquire/release lifecycle of pooled GameObjects.

The manager integrates with the GameWorld to clone prefabs during pool initialization and to look up GameObjects by their EntityHandle during acquire/release operations.

## Lifecycle

1. **Configuration**: Add pool configurations via `addPoolConfig()`. 2. **Initialization**: Call `init()` to create pools and populate them with cloned prefab instances. This **locks** the pools. 3. **Runtime**: Use `acquire()` and `release()` to manage entity lifecycle.

## Pool Locking

After `init()` completes, each pool is **locked**. A locked pool:

  • Cannot accept new EntityHandles via `addInactive()`
  • Has its sparse arrays sized based on min/max EntityIds
  • Is ready for O(1) acquire/release operations

This design optimizes memory layout but means the pool size is fixed at initialization time.

## Trade-offs

  • **Fixed Capacity**: Pool size cannot grow after initialization. If more entities are needed, `acquire()` returns nullptr when exhausted.
  • **Memory Overhead**: Sparse arrays are sized for the EntityId range, which may waste memory if EntityIds are not contiguous.
  • **Initialization Cost**: All prefab clones are created upfront during `init()`, which may cause a startup delay for large pools.

## Example

```cpp GameObjectPoolManager poolManager;

// Create prefab auto bulletPrefab = gameWorld.addGameObject(); bulletPrefab.add<RenderableComponent>(mesh, material); bulletPrefab.add<Move2DComponent>(); bulletPrefab.setActive(false);

auto config = std::make_unique<GameObjectPoolConfig>( bulletPoolId, bulletPrefab, 100 ); poolManager.addPoolConfig(std::move(config));

poolManager.init(gameWorld);

// Acquire returns std::optional<GameObject> if (auto bullet = poolManager.acquire(bulletPoolId)) { bullet->get<TranslationStateComponent>()->setTranslation(spawnPos); bullet->setActive(true); }

// Release back to pool poolManager.release(bulletPoolId, bullet->entityHandle()); ```

See Also

GameObjectPool

See Also

GameObjectPoolRegistry

See Also

Manager

Definition at line 105 of file GameObjectPoolManager.ixx.

Public Member Typedefs

EngineRoleTag

using helios::engine::runtime::pooling::GameObjectPoolManager::EngineRoleTag = helios::engine::common::tags::ManagerRole

Public Member Functions

acquire()

std::optional< helios::engine::ecs::GameObject > helios::engine::runtime::pooling::GameObjectPoolManager::acquire (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId)
inline nodiscard

Acquires an inactive GameObject from the pool.

Retrieves the next available inactive entity and calls `onAcquire()` to trigger component initialization hooks. The caller is responsible for activating the entity via `setActive(true)`.

If an acquired entity is no longer valid in the GameWorld (stale handle), it is removed from the pool and the next available entity is tried.

Parameters
gameObjectPoolId

The pool to acquire from.

Returns

Optional containing the acquired GameObject if available, std::nullopt if the pool is exhausted.

Definition at line 266 of file GameObjectPoolManager.ixx.

266 [[nodiscard]] std::optional<helios::engine::ecs::GameObject> acquire(
268 ) {
270
271 auto* gameObjectPool = pool(gameObjectPoolId);
272
273 while (gameObjectPool->acquire(entityHandle)) {
274
275 auto worldGo = gameWorld_->find(entityHandle);
276
277 if (worldGo) {
278 worldGo->onAcquire();
279 return worldGo;
280 }
281
282 // we assume the pool is owned by this gameWorld,
283 // so removing this entityHandle does not impact another gameWorld that is
284 // using this pool
285 gameObjectPool->releaseAndRemove(entityHandle);
286 }
287
288 return std::nullopt;
289
290 }

Reference pool.

addPoolConfig()

GameObjectPoolManager & helios::engine::runtime::pooling::GameObjectPoolManager::addPoolConfig (std::unique_ptr< GameObjectPoolConfig > gameObjectPoolConfig)
inline

Registers a pool configuration for later initialization.

The configuration specifies the pool ID, capacity, and prefab to use for cloning. Configurations are processed during `init()`.

Parameters
gameObjectPoolConfig

The pool configuration to register.

Returns

Reference to this manager for method chaining.

Exceptions
std::runtime_error

If a pool with the same ID is already registered.

Definition at line 189 of file GameObjectPoolManager.ixx.

189 GameObjectPoolManager& addPoolConfig(std::unique_ptr<GameObjectPoolConfig> gameObjectPoolConfig) {
190
191 if (poolConfigs_.contains(gameObjectPoolConfig->gameObjectPoolId)) {
192 throw std::runtime_error("Pool already registered with this manager");
193 }
194
195 poolConfigs_[gameObjectPoolConfig->gameObjectPoolId] = std::move(gameObjectPoolConfig);
196
197 return *this;
198 }

flush()

void helios::engine::runtime::pooling::GameObjectPoolManager::flush (helios::engine::runtime::world::UpdateContext & update_context)
inline noexcept

Manager flush callback (currently unused).

Reserved for future use. May be used to process deferred release requests or pool maintenance operations.

Parameters
gameWorld

The associated GameWorld.

update_context

The current frame's update context.

Definition at line 331 of file GameObjectPoolManager.ixx.

331 void flush(
333 ) noexcept {
334
335 }

init()

void helios::engine::runtime::pooling::GameObjectPoolManager::init (helios::engine::runtime::world::GameWorld & gameWorld)
inline

Initializes all registered pools.

Creates GameObjectPool instances from the pending configurations and populates them by cloning the specified prefabs into the GameWorld.

Parameters
gameWorld

The GameWorld to associate with this manager.

Definition at line 300 of file GameObjectPoolManager.ixx.

301
302 gameWorld_ = &gameWorld;
303
304 for (const auto& [gameObjectPoolId, poolConfig] : poolConfigs_) {
305
306 auto pool = std::make_unique<helios::engine::runtime::pooling::GameObjectPool>(
307 poolConfig->amount);
308
309 pools_.addPool(gameObjectPoolId, std::move(pool));
310
311 for (auto [entity, pic] : gameWorld.view<helios::engine::runtime::pooling::components::PrefabIdComponent>().whereEnabled()) {
312 if (pic->prefabId() == poolConfig->prefabId) {
313 fillPool(gameObjectPoolId, entity);
314 break;
315 }
316 }
317
318 }
319
320 };

References pool and helios::engine::runtime::world::GameWorld::view.

pool()

GameObjectPool * helios::engine::runtime::pooling::GameObjectPoolManager::pool (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId)
inline nodiscard

Retrieves a pool by its ID.

Parameters
gameObjectPoolId

The pool ID to look up.

Returns

Pointer to the GameObjectPool.

Precondition

The pool must be registered with this manager.

Definition at line 346 of file GameObjectPoolManager.ixx.

346 [[nodiscard]] GameObjectPool* pool(
348 ) const {
349 assert(pools_.has(gameObjectPoolId) && "GameObjectPoolId not registered with this manager");
350 return pools_.pool(gameObjectPoolId);
351 }

Referenced by acquire, init, poolSnapshot, release and reset.

poolSnapshot()

helios::engine::runtime::pooling::GameObjectPoolSnapshot helios::engine::runtime::pooling::GameObjectPoolManager::poolSnapshot (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId)
inline nodiscard

Returns a snapshot of the pool's current state.

Provides the active and inactive counts for monitoring and debugging purposes.

Parameters
gameObjectPoolId

The pool to query.

Returns

A GameObjectPoolSnapshot containing active and inactive counts.

Definition at line 210 of file GameObjectPoolManager.ixx.

212 ) const {
213 auto* gameObjectPool = pool(gameObjectPoolId);
214
215 return {
216 gameObjectPool->activeCount(), gameObjectPool->inactiveCount()
217 };
218 }

Reference pool.

Referenced by helios::engine::runtime::spawn::policy::amount::SpawnAll::getAmount.

release()

std::optional< helios::engine::ecs::GameObject > helios::engine::runtime::pooling::GameObjectPoolManager::release (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId, const helios::engine::ecs::EntityHandle & entityHandle)
inline

Releases a GameObject back to its pool.

Marks the entity as inactive in both the pool and the GameWorld. Calls `onRelease()` on the GameObject to trigger component cleanup hooks, then deactivates it.

Parameters
gameObjectPoolId

The pool that owns this entity.

entityHandle

The EntityHandle of the entity to release.

Returns

Optional containing the released GameObject if found, std::nullopt if the entity was not found in the GameWorld.

Definition at line 233 of file GameObjectPoolManager.ixx.

233 std::optional<helios::engine::ecs::GameObject> release(
235 const helios::engine::ecs::EntityHandle& entityHandle
236 ) {
237 auto* gameObjectPool = pool(gameObjectPoolId);
238
239 auto worldGo = gameWorld_->find(entityHandle);
240
241 if (worldGo) {
242 if (gameObjectPool->release(entityHandle)) {
243 worldGo->onRelease();
244 worldGo->setActive(false);
245 }
246 }
247
248 return worldGo;
249 }

Reference pool.

Referenced by reset.

reset()

void helios::engine::runtime::pooling::GameObjectPoolManager::reset ()
inline

Resets all pools by releasing all active GameObjects.

Iterates through all registered pools and releases every active entity back to its pool. This effectively returns all pooled objects to their inactive state without destroying them.

Useful for level transitions or game restarts where all pooled objects should be recycled.

See Also

reset(const types::GameObjectPoolId)

Definition at line 365 of file GameObjectPoolManager.ixx.

365 void reset() {
366 for (auto& [poolId, _] : pools_.pools()) {
367 reset(poolId);
368 }
369 }

Reference reset.

Referenced by reset.

reset()

void helios::engine::runtime::pooling::GameObjectPoolManager::reset (const types::GameObjectPoolId poolId)
inline

Reset the pool with the specified poolId.

Releases every active entity back to its pool specified by poolId. This effectively returns all pooled objects to their inactive state without destroying them.

Parameters
poolId

The ID of the pool to reset.

Definition at line 380 of file GameObjectPoolManager.ixx.

380 void reset(const types::GameObjectPoolId poolId) {
381
382 const auto poolPtr = pool(poolId);
383
384 auto activeSpan = poolPtr->activeGameObjects();
385 auto toRelease = std::vector(activeSpan.begin(), activeSpan.end());
386 for (auto entityHandle : toRelease) {
387 release(poolId, entityHandle);
388 }
389 }

References pool and release.

Private Member Functions

fillPool()

void helios::engine::runtime::pooling::GameObjectPoolManager::fillPool (const helios::engine::runtime::pooling::types::GameObjectPoolId gameObjectPoolId, helios::engine::ecs::GameObject gameObjectPrefab)
inline

Populates a pool with cloned prefab instances and locks it.

Clones the prefab GameObject until the pool reaches its configured capacity. Each clone is: 1. Added to the GameWorld 2. Immediately deactivated (`setActive(false)`) 3. Prepared for pooling (`onRelease()`) 4. Registered as inactive in the pool

After all clones are created, the pool is **locked** via `lock()`. Locking finalizes the sparse array sizing based on the min/max EntityIds and enables O(1) acquire/release operations. Once locked, no new EntityHandles can be added to the pool.

Parameters
gameObjectPoolId

The pool to fill.

gameObjectPrefab

The prefab to clone.

Postcondition

The pool is locked and ready for acquire/release operations.

Definition at line 153 of file GameObjectPoolManager.ixx.

153 void fillPool(
155 helios::engine::ecs::GameObject gameObjectPrefab
156 ) {
158
159 auto* gameObjectPool = pool(gameObjectPoolId);
160
161 const size_t used = gameObjectPool->activeCount() + gameObjectPool->inactiveCount();
162 const size_t space = used < gameObjectPool->size() ? gameObjectPool->size() - used : 0;
163
164 for (size_t i = 0; i < space; i++) {
165 helios::engine::ecs::GameObject go = gameWorld_->clone(gameObjectPrefab);
166 go.setActive(false);
167 go.onRelease();
168 gameObjectPool->addInactive(go.entityHandle());
169 }
170
171 gameObjectPool->lock();
172 }

Private Member Attributes

gameWorld_

helios::engine::runtime::world::GameWorld* helios::engine::runtime::pooling::GameObjectPoolManager::gameWorld_ = nullptr

Non-owning pointer to the associated GameWorld.

Set during `init()`. Used for cloning prefabs and looking up GameObjects by their EntityHandle.

Definition at line 121 of file GameObjectPoolManager.ixx.

poolConfigs_

std::unordered_map< helios::engine::runtime::pooling::types::GameObjectPoolId, std::unique_ptr<GameObjectPoolConfig> > helios::engine::runtime::pooling::GameObjectPoolManager::poolConfigs_

Pending pool configurations awaiting initialization.

Configurations are consumed during `init()` to create and populate the actual pools.

Definition at line 131 of file GameObjectPoolManager.ixx.

131 std::unique_ptr<GameObjectPoolConfig>> poolConfigs_;

pools_

helios::engine::runtime::pooling::GameObjectPoolRegistry helios::engine::runtime::pooling::GameObjectPoolManager::pools_ {}

Registry of GameObjectPools for entity recycling.

Pools enable efficient reuse of GameObjects without repeated allocation/deallocation. Each pool is identified by a GameObjectPoolId.

Definition at line 113 of file GameObjectPoolManager.ixx.


The documentation for this class was generated from the following file:


Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.