Optimization Patterns

June 19, 2026 ยท View on GitHub

Performance-oriented patterns in FronkonGames.GameWork.Foundation for reducing allocation overhead in hot paths.

PatternFolderRole
Object PoolObjectPoolReuse instances instead of allocating every time

Object Pool

Why use it: Reuse objects instead of allocating and destroying them every frame. Instantiate/Destroy and heavy new calls cause GC spikes that show up as frame hitches. A pool pre-creates a batch, hands out instances on Get(), and recycles them on Release() after you reset their state. Essential for projectiles, particle-like VFX, floating damage numbers, list rows, and any burst of short-lived objects with a predictable peak count.

ObjectPool.cs

MemberDescription
ObjectPool<T>(createFunc, onGet, onRelease, initialSize)Constructor with optional callbacks and pre-warm count
Get()Pop from pool or create via createFunc
Release(T item)Push back after optional onRelease callback
Clear()Discard all pooled instances
CountAvailableItems currently in the pool

T must be a reference type (class). Use onGet / onRelease to reset state, enable/disable GameObjects, clear lists, reset timers.

using FronkonGames.GameWork.Foundation;
using UnityEngine;

public class CoinPickup : MonoBehaviour
{
  public void ResetState() => transform.localScale = Vector3.one;
}

// Scene: CoinSpawner, pre-warm 20 coins at startup
var coinPool = new ObjectPool<CoinPickup>(
  createFunc: () =>
  {
    GameObject go = Object.Instantiate(coinPrefab);
    go.SetActive(false);
    return go.GetComponent<CoinPickup>();
  },
  onGet: coin => coin.gameObject.SetActive(true),
  onRelease: coin =>
  {
    coin.ResetState();
    coin.gameObject.SetActive(false);
  },
  initialSize: 20
);

// Spawn
CoinPickup coin = coinPool.Get();
coin.transform.position = spawnPoint;

// Recycle when collected
coinPool.Release(coin);

When to use

Use pool whenSkip pool when
Many short-lived objects (projectiles, VFX, UI rows)Few instances that live for the whole scene
Instantiate/Destroy causes GC spikesObject state is too complex to reset safely
Peak count is bounded and predictableOne-off objects (boss intro, cutscene props)

Pre-warm with initialSize to avoid allocation during the first burst. Get() only calls createFunc when the pool is empty.


Tests