U
18 / 22 · 9 min
FAQ

Instantiate: spawning prefabs, and reusing them

the short answer

How do I spawn objects from code?

Make the thing a prefab, hold a reference to it in a public field, and call Instantiate(prefab, position, rotation). Drag the prefab from the Project panel into that field — dragging the copy that sits in the Hierarchy instead is the mistake behind half of all spawner bugs.

Spawning is one function, Instantiate, and one habit that decides whether it works: the thing you spawn has to be a prefab from the Project panel, not the copy sitting in your scene.

Make the prefab first

  1. 1

    Build the object in the scene until it is exactly what you want to spawn — mesh, material, collider, scripts, all of it.

  2. 2

    Drag it from the Hierarchy into Assets/Prefabs. Its name turns blue: it is a prefab now, and it lives on disk.

  3. 3

    Delete the one left in the scene. The prefab is the master copy; the scene copy would just be one more enemy standing there at startup.

Instantiate

Spawner.cs — drag the PREFAB into the slot, not the scene object
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public GameObject prefab;
    public Transform parent;        // optional, keeps the Hierarchy tidy
    public float interval = 1.5f;

    float next;

    void Update()
    {
        if (Time.time < next) return;
        next = Time.time + interval;

        Vector3 where = transform.position + Random.insideUnitSphere * 3f;
        where.y = transform.position.y;

        GameObject spawned = Instantiate(prefab, where, Quaternion.identity, parent);

        // Instantiate returns the new copy. Configure that, never the prefab —
        // writing to prefab.something edits the asset on disk.
        spawned.name = "Enemy " + Time.frameCount;
    }
}

Three things people forget

  • Instantiate copies everything, including the prefab's scale and its children. If the spawned object is the wrong size, the prefab is the wrong size.

  • Passing a parent keeps the Hierarchy readable, but the object then inherits the parent's scale. Parent to something with scale 1, or spawn without a parent and call SetParent(parent, true) afterwards.

  • Quaternion.identity means no rotation. Writing transform.rotation there instead makes every spawn face the way the spawner does, which is usually what you actually wanted.

Destroy, and why spawners kill frame rate

Every Instantiate allocates and every Destroy leaves rubbish for the garbage collector. A spawner running every frame will stutter on a phone within a minute. For bullets and effects — anything that appears hundreds of times — reuse instead of recreating.

The smallest pool that is worth having
using System.Collections.Generic;
using UnityEngine;

public class SimplePool : MonoBehaviour
{
    public GameObject prefab;
    readonly Queue<GameObject> idle = new();

    public GameObject Get(Vector3 at)
    {
        GameObject go = idle.Count > 0 ? idle.Dequeue() : Instantiate(prefab);
        go.transform.position = at;
        go.SetActive(true);
        return go;
    }

    // Call this instead of Destroy.
    public void Release(GameObject go)
    {
        go.SetActive(false);
        idle.Enqueue(go);
    }
}

the lesson that builds this

Spawn a grid from code

This post is a standalone recipe. In the course, the same thing is built as part of the one project that runs through all five tabs — Basics, lesson 08.