Prefabs & Spawning
A prefab is a saved GameObject template, like a blueprint. You design something once (an enemy, a bullet, a coin) and then create as many copies as you want, in the Editor or from code with Instantiate.
Making a prefab
A cookie cutter. The prefab asset is the cutter in the drawer, and each instance in the scene is a cookie. Reshape the cutter and every future cookie changes, and Unity even updates the cookies already placed in your scenes. Adding sprinkles to one cookie (an override) doesn't change the cutter or the other cookies.
- Build the GameObject in your scene with all its components and children.
- Drag it from the Hierarchy into the Project window. It turns blue in the Hierarchy and a prefab asset appears in the Project.
- You can now delete it from the scene. The prefab asset stays.
Prefab asset vs. prefab instance
| Prefab asset | Prefab instance | |
|---|---|---|
| Where it lives | Project window (a .prefab file) | In a scene / the Hierarchy |
| Editing it | Double-click to open Prefab Mode. Changes apply to every instance. | Changes apply only to this copy (an "override", shown in bold in the Inspector) |
| Exists at runtime? | Only as data to copy from | Yes, it's a real object in the scene |
To push an instance's overrides back to the asset, use the Overrides dropdown at the top of the Inspector and choose Apply All.
Prefab Variants (right-click a prefab > Create > Prefab Variant) inherit from another prefab. For example "FastEnemy" can be a variant of "Enemy" with a different speed. Change the base and the variant updates too.
Spawning a prefab from code
using UnityEngine;
public class CoinSpawner : MonoBehaviour
{
[SerializeField] private GameObject coinPrefab; // drag the prefab asset here
[SerializeField] private int count = 10;
void Start()
{
for (int i = 0; i < count; i++)
{
Vector3 pos = new Vector3(i * 2f, 1f, 0f);
Instantiate(coinPrefab, pos, Quaternion.identity);
}
}
}
Tip: reference the prefab by its script type
If your prefab has a script on it, make the field that type. Instantiate then gives you the script directly, so you don't need GetComponent.
using UnityEngine;
public class Gun : MonoBehaviour
{
[SerializeField] private Bullet bulletPrefab; // Bullet is a MonoBehaviour on the prefab
[SerializeField] private Transform muzzle;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Bullet b = Instantiate(bulletPrefab, muzzle.position, muzzle.rotation);
b.speed = 30f; // configure the new copy
}
}
}
What happens at runtime
Instantiatemakes a full copy of the prefab: the GameObject, all children, and all components with their saved values.- The copy is placed in the active scene at the position and rotation you gave.
AwakeandOnEnablerun on the copy's scripts immediately, beforeInstantiatereturns.Startruns later, just before the copy's firstUpdate(so you can still set fields likeb.speedabove beforeStartuses them).- The copy is named after the prefab with "(Clone)" added, for example "Bullet(Clone)".
Removing spawned objects
Use Destroy. The optional second argument is a delay in seconds.
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float speed = 20f;
void Start()
{
Destroy(gameObject, 3f); // clean up after 3 seconds, even if it hits nothing
}
void Update()
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
Object pooling (for things spawned very often)
Creating and destroying hundreds of objects per second (bullets, particles) creates work for the garbage collector and can cause stutters. A pool reuses objects instead: deactivate them instead of destroying, and reactivate them instead of instantiating. Unity has a built-in ObjectPool<T> in UnityEngine.Pool:
using UnityEngine;
using UnityEngine.Pool;
public class PooledGun : MonoBehaviour
{
[SerializeField] private GameObject bulletPrefab;
private ObjectPool<GameObject> pool;
void Awake()
{
pool = new ObjectPool<GameObject>(
createFunc: () => Instantiate(bulletPrefab),
actionOnGet: b => b.SetActive(true),
actionOnRelease: b => b.SetActive(false),
actionOnDestroy: b => Destroy(b),
defaultCapacity: 20);
}
public GameObject Fire()
{
GameObject b = pool.Get();
b.transform.SetPositionAndRotation(transform.position, transform.rotation);
return b;
}
// Call this from the bullet instead of Destroy(gameObject).
public void ReturnBullet(GameObject b)
{
pool.Release(b);
}
}
Awake and Start only run the first time. Put "reset" code (health, timers) in OnEnable.Common Mistakes
- Dragging a scene object instead of the prefab asset into the field. If that object gets destroyed, the field becomes empty (missing). Always drag from the Project window.
- Modifying the prefab asset at runtime (
coinPrefab.transform.localScale = ...). That changes the template, not the copy, and in the Editor can even save to disk. Modify the value returned byInstantiate. Destroy(this)vsDestroy(gameObject).thisis only your script component. The object stays. UsegameObjectto remove the whole thing.
See also
- Object (Instantiate, Destroy)
- Object Pooling (full guide)
- GameObject
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Unity documentation.