# How to Use TEngine's Object Pool for GameObjects: A Complete Guide to Zero-Allocation Pooling

> Learn to use TEngine's object pool for GameObjects, eliminating Instantiate/Destroy overhead. Maximize performance and reduce garbage collection with this zero-allocation pooling guide.

- Repository: [ALEX/tengine](https://github.com/alex-rachel/tengine)
- Tags: how-to-guide
- Published: 2026-02-24

---

**TEngine's ObjectPoolModule eliminates runtime `Instantiate` and `Destroy` overhead by recycling GameObject instances through a generic pool system that leverages the `ObjectBase` lifecycle and `IObjectPoolModule` factory methods.**

TEngine (alex-rachel/tengine) provides a production-ready pooling framework designed specifically for Unity's GameObject management challenges. By implementing the abstract `ObjectBase` class and utilizing the `ObjectPoolModule`, you can maintain stable frame rates and minimize garbage collection stalls during intense gameplay moments. This guide walks through the exact implementation pattern used in TEngine's core runtime, referencing the actual source files that power the system.

## Understanding TEngine's Object Pool Architecture

The pooling system consists of three tightly integrated components defined across four key source files.

- **[`IObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/IObjectPoolModule.cs)** (lines 61-76): Defines the contract for creating, retrieving, and destroying pool instances. This interface exposes factory methods like `CreateMultiSpawnObjectPool<T>()` and `CreateSingleSpawnObjectPool<T>()`.

- **[`ObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPoolModule.cs)** (lines 740-775): The concrete implementation that manages pool lifecycle and provides the internal `ObjectPool<T>` generic class. This file contains the capacity management and auto-release logic.

- **[`ObjectBase.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectBase.cs)**: The abstract base class that all pooled objects must inherit. It defines the critical `OnSpawn()` and `OnDespawn()` virtual methods that handle GameObject instantiation and deactivation.

- **[`ObjectPool.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPool.cs)** (embedded in ObjectPoolModule): The generic container that tracks active and inactive instances, ensuring thread-safe operations on the Unity main thread.

## Step 1: Define a Pooled GameObject Type

To pool a GameObject, create a wrapper class that inherits from **ObjectBase**. This class stores your prefab reference and implements the spawn/despawn lifecycle hooks.

```csharp
using TEngine.Runtime.Module.ObjectPoolModule;
using UnityEngine;

/// <summary>
/// Wrapper for pooling GameObject prefabs. 
/// References ObjectBase defined in ObjectBase.cs.
/// </summary>
public sealed class PooledGameObject : ObjectBase
{
    public GameObject Prefab;   // Assigned during pool initialization
    private GameObject _instance;

    // Called automatically when Spawn() pulls from pool
    protected override void OnSpawn()
    {
        _instance = Object.Instantiate(Prefab);
    }

    // Called automatically when Despawn() returns to pool
    protected override void OnDespawn()
    {
        if (_instance != null)
        {
            _instance.SetActive(false);
            _instance.transform.SetParent(null);
        }
    }

    public GameObject GameObject => _instance;
}

```

The **OnSpawn** method handles instantiation only when the pool needs a new active instance, while **OnDespawn** deactivates rather than destroys, preparing the object for immediate reuse.

## Step 2: Create and Configure the Pool

Use the **IObjectPoolModule** interface to create either a multi-spawn or single-spawn pool. Multi-spawn pools support many simultaneously active objects (e.g., bullets), while single-spawn pools enforce only one active instance at a time (e.g., UI popups).

```csharp
using TEngine.Runtime.Module.ObjectPoolModule;
using UnityEngine;

public class BulletPoolManager : MonoBehaviour
{
    [SerializeField] private GameObject bulletPrefab;
    private IObjectPool<PooledGameObject> _bulletPool;

    private void Awake()
    {
        // Retrieve the module implementation from ObjectPoolModule.cs
        var poolModule = ModuleSystem.GetModule<IObjectPoolModule>();

        // CreateMultiSpawnObjectPool<T> defined at lines 740-775 in ObjectPoolModule.cs
        _bulletPool = poolModule.CreateMultiSpawnObjectPool<PooledGameObject>(
            name: "BulletPool",
            capacity: 200);

        // InitObject runs once per internal slot creation
        _bulletPool.InitObject(obj => obj.Prefab = bulletPrefab);
    }

    public IObjectPool<PooledGameObject> GetPool() => _bulletPool;
}

```

The **capacity** parameter (set to 200 in this example) caps the maximum number of live objects. When capacity is reached, the pool recycles the oldest inactive instance rather than allocating new memory.

## Step 3: Spawn and Despawn at Runtime

With the pool initialized, retrieve instances via **Spawn()** and return them via **Despawn()**. This pattern eliminates runtime allocations entirely after the initial warm-up phase.

### Spawning a Bullet

```csharp
public class WeaponController : MonoBehaviour
{
    private BulletPoolManager _poolManager;

    private void Start()
    {
        _poolManager = FindObjectOfType<BulletPoolManager>();
    }

    public void Fire(Vector3 position, Vector3 direction)
    {
        // Spawn() invokes OnSpawn() automatically
        var pooledObj = _poolManager.GetPool().Spawn();
        
        var bulletGO = pooledObj.GameObject;
        bulletGO.transform.position = position;
        bulletGO.transform.forward = direction;
        bulletGO.SetActive(true);
    }
}

```

### Returning to the Pool

```csharp
public class Projectile : MonoBehaviour
{
    private IObjectPool<PooledGameObject> _ownerPool;
    private float _spawnTime;

    public void SetPool(IObjectPool<PooledGameObject> pool) 
    {
        _ownerPool = pool;
        _spawnTime = Time.time;
    }

    private void Update()
    {
        // Return after 5 seconds or on impact
        if (Time.time - _spawnTime > 5f)
        {
            var pooledComponent = GetComponent<PooledGameObject>();
            _ownerPool.Despawn(pooledComponent); // Invokes OnDespawn()
        }
    }
}

```

The **Despawn** method immediately recycles the object, making it available for the next `Spawn()` call without triggering garbage collection.

## Performance Characteristics and Optimization

TEngine's implementation addresses specific Unity performance constraints through several architectural choices:

- **Zero Runtime Allocation**: After initial pool warm-up, no `Instantiate` or `Destroy` calls occur, eliminating GC.Alloc spikes.
- **Fixed Memory Budget**: The `capacity` argument in `CreateMultiSpawnObjectPool<T>()` creates a hard ceiling on memory usage.
- **Main Thread Safety**: All internal list operations in [`ObjectPool.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPool.cs) execute on Unity's main thread, preventing race conditions with the engine's native GameObject API.
- **Automatic Lifecycle Hooks**: The `OnSpawn`/`OnDespawn` pattern ensures pooled objects reset their state correctly without manual tracking.

Monitor pool utilization at runtime by checking the **Count** and **InactiveCount** properties exposed through `ObjectPoolBase`, allowing you to tune capacity values based on actual gameplay metrics.

## Summary

- **ObjectBase** subclasses wrap GameObject prefabs and define instantiation logic via `OnSpawn()` and cleanup via `OnDespawn()`.
- **IObjectPoolModule** provides factory methods `CreateMultiSpawnObjectPool<T>()` and `CreateSingleSpawnObjectPool<T>()` (implemented in [`ObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPoolModule.cs) lines 740-775).
- **Capacity limits** prevent unbounded memory growth; excess spawn requests recycle inactive instances.
- **Spawn()** and **Despawn()** operations are allocation-free after pool initialization, maintaining consistent frame times during high-intensity spawning scenarios.

## Frequently Asked Questions

### What is the difference between CreateMultiSpawnObjectPool and CreateSingleSpawnObjectPool?

**CreateMultiSpawnObjectPool<T>** allows an unlimited number of simultaneously active objects from the pool, making it ideal for projectiles, enemies, or particles. **CreateSingleSpawnObjectPool<T>** enforces that only one instance of type T can be active at any moment, which is useful for singleton UI panels or exclusive audio sources that must not overlap.

### How does TEngine handle the actual GameObject instantiation?

According to [`ObjectBase.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectBase.cs), the pool calls the virtual `OnSpawn()` method when a new instance is needed. Your derived class implements this to run `Object.Instantiate(Prefab)`, giving you full control over instantiation parameters. When despawning, `OnDespawn()` handles deactivation or parenting logic without destroying the underlying GameObject.

### Can I set a maximum capacity for my GameObject pool?

Yes. The `CreateMultiSpawnObjectPool<T>()` method accepts a `capacity` parameter (as shown in [`ObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPoolModule.cs) lines 740-775). This integer defines the maximum number of objects the pool will maintain. Once reached, spawning either recycles the oldest inactive object or fails gracefully depending on your configuration, preventing memory bloat during unexpected gameplay spikes.

### Where are the core ObjectPool files located in the TEngine repository?

The interface resides in [`UnityProject/Assets/TEngine/Runtime/Module/ObjectPoolModule/IObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Module/ObjectPoolModule/IObjectPoolModule.cs) (lines 61-76). The concrete implementation is in [`ObjectPoolModule.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPoolModule.cs) (lines 740-775 for factory methods, lines 1172-1239 for destruction logic). The base class definition is in [`ObjectBase.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectBase.cs), and the generic pool container logic is in [`ObjectPool.cs`](https://github.com/alex-rachel/tengine/blob/main/ObjectPool.cs).