Lesson 18 +10 XP

Instantiation & Destruction

Instantiation & Destruction

Creating objects dynamically (like shooting bullets or spawning enemies) and removing them (like collecting coins or deleting destroyed entities) are fundamental to gameplay development.

1. Spawning GameObjects: Instantiate

The Instantiate function takes a template GameObject (or Prefab) and duplicates it in the active scene:

using UnityEngine;

public class Weapon : MonoBehaviour
{
    [SerializeField] private GameObject bulletPrefab; // Assign in the Inspector
    [SerializeField] private Transform spawnPoint;     // Point where bullets spawn

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Spawn bulletPrefab at spawnPoint's position and rotation
            Instantiate(bulletPrefab, spawnPoint.position, spawnPoint.rotation);
        }
    }
}

Generics and Typing

By default, Instantiate returns a generic Object. However, you can pass a component class type directly to automatically retrieve the component on the newly spawned object without calling GetComponent:

// Spawns prefab and directly stores a reference to its Bullet script:
Bullet newBullet = Instantiate<Bullet>(bulletPrefab, spawnPoint.position, spawnPoint.rotation);
newBullet.SetDamageValue(25);

Spawning with Parents

To instantiate an object as a child of another Transform, pass the parent Transform as a parameter:

// Spawns UI panels nested inside the Canvas:
Instantiate(uiPanelPrefab, canvasTransform);

2. Removing GameObjects: Destroy

To remove a GameObject or a component from the scene, use the Destroy function.

> [!CAUTION] > Calling Destroy(this) only deletes the active script component instance, leaving the parent GameObject in the scene. To delete the entire GameObject, always pass gameObject as the argument:

void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Projectile"))
    {
        // 1. Destroy the projectile object
        Destroy(collision.gameObject);

        // 2. Destroy this script's GameObject
        Destroy(gameObject);
    }
}

3. Delayed Destruction

You can pass an optional float parameter to schedule a destruction after a specific duration:

// Spawns a smoke effect, and deletes it 3.5 seconds later to clean up the scene
GameObject smoke = Instantiate(smokePrefab, position, rotation);
Destroy(smoke, 3.5f);

4. Performance Note: Object Pooling

Repeatedly calling Instantiate and Destroy causes the CPU to allocate heap memory, forcing the garbage collector to run and creating frame stutters. For high-frequency objects (like laser beams or blood splatters), use Object Pooling:

  • Pre-spawn 20 bullet objects at startup and set them to inactive: gameObject.SetActive(false).
  • When shooting, grab an inactive bullet, move it to the gun tip, and set it active: gameObject.SetActive(true).
  • When the bullet hits a wall, disable it instead of destroying it.

TL;DR

  • Use Instantiate to clone GameObjects or Prefabs at runtime.
  • Cast generics (e.g. Instantiate<T>) to access components on the clone instantly.
  • Pass gameObject to Destroy to delete the entity, not just the script component.
  • Delay destruction by providing a second float parameter (seconds).
  • Use Object Pools for high-frequency assets to prevent garbage collector stutters.