Optimization Techniques In Unity

Last Updated : 4 May, 2026

Optimization means making your game use less CPU, GPU and memory. A well-optimized game runs at 60 frames per second (FPS) even on low-end devices.

  • Reduces lag and stuttering
  • Saves battery on mobile devices
  • Allows more objects on screen

Technique 1: Object Pooling

Creating and destroying objects repeatedly causes lag spikes. Object pooling reuses objects instead.

C#
public class BulletPool : MonoBehaviour
{
    public GameObject bulletPrefab;
    public int poolSize = 20;
    private Queue<GameObject> pool = new Queue<GameObject>();
    void Start()
    {
        for (int i = 0; i < poolSize; i++)
        {
            GameObject bullet = Instantiate(bulletPrefab);
            bullet.SetActive(false);
            pool.Enqueue(bullet);
        }
    }
    public GameObject GetBullet()
    {
        GameObject bullet = pool.Dequeue();
        bullet.SetActive(true);
        pool.Enqueue(bullet);
        return bullet;
    }
}

Instead of Instantiate() and Destroy(), you activate and deactivate objects. This eliminates garbage collection spikes.

Technique 2: Reduce Draw Calls

Each object with a unique material creates a draw call. Too many draw calls slow down the GPU.

Problems that increase draw calls

  • 10 trees with 10 different materials
  • UI elements with individual images
  • Characters with separate material per body part

Solutions

  • Use texture atlases (one image for multiple objects)
  • Share materials between objects
  • Combine meshes for static objects

Technique 3: Limit Update() Usage

Every script with Update() runs every frame. Too many Update() methods hurt performance.

Bad:

C#
void Update()
{
    // Heavy calculation every frame
    FindObjectOfType<Enemy>();
    GetComponent<Renderer>().material.color = Color.red;
}

Better:

C#
void Start()
{
    enemy = FindObjectOfType<Enemy>();  // Find once
    myRenderer = GetComponent<Renderer>();
}
void Update()
{
    // Use cached references
    myRenderer.material.color = Color.red;
}

Best: Use Invoke or Coroutines for non-critical tasks

C#
void Start()
{
    InvokeRepeating("DoHeavyTask", 0f, 0.5f);  // Run every 0.5 seconds, not every frame
}

Technique 4: Pool Particles

Particle effects create many GameObjects. Pool them instead.

C#
public class ParticlePool : MonoBehaviour
{
    public ParticleSystem particlePrefab;
    private Queue<ParticleSystem> pool = new Queue<ParticleSystem>();
    public void PlayAt(Vector3 position)
    {
        ParticleSystem ps;
        if (pool.Count > 0)
            ps = pool.Dequeue();
        else
            ps = Instantiate(particlePrefab);
        
        ps.transform.position = position;
        ps.Play();
        StartCoroutine(ReturnToPool(ps, ps.main.duration));
    }
    IEnumerator ReturnToPool(ParticleSystem ps, float delay)
    {
        yield return new WaitForSeconds(delay);
        ps.Stop();
        pool.Enqueue(ps);
    }
}

Technique 5: Optimize UI

UI can be a major performance killer.

Tips for UI optimization:

  • Disable Raycast Target on non-interactive UI elements.
  • Use Canvas Group to hide entire menus.
  • Separate frequently updating UI (score) into its own Canvas.
  • Use TextMeshPro instead of legacy Text.

Example:

C#
// Bad: Entire UI updates every frame
void Update()
{
    scoreText.text = "Score: " + score;  // Forces UI rebuild
}
// Good: Update only when needed
public void UpdateScore()
{
    scoreText.text = "Score: " + score;  // Called only when score changes
}

Technique 6: Level of Detail (LOD)

Distant objects don't need high detail. LOD uses simpler models for far away objects.

Setup:

  1. Select a 3D model.
  2. Add Component - LOD Group.
  3. Assign high-detail model for LOD 0 (close).
  4. Assign medium-detail model for LOD 1 (medium distance).
  5. Assign low-detail model for LOD 2 (far).

Technique 7: Occlusion Culling

Unity renders everything in camera view, even behind walls. Occlusion culling hides objects blocked by others.

Setup:

  1. Select objects - Check "Occluder Static" and "Occludee Static" in Inspector.
  2. Window - Rendering - Occlusion Culling.
  3. Click "Bake".

Without occlusion culling, all objects are rendered. With occlusion culling, objects behind walls are not rendered.

Comment
Article Tags:

Explore