Creating and Destroying Objects

Learn how to create and destroy GameObjects in Unity. Covers Instantiate() and Destroy() functions.

What is Creating and Destroying Objects?

Dynamically creating and destroying objects is a very important feature in game development. For example, when firing bullets, you create bullet objects, and when they go off-screen, you delete them.

Basic Concepts

  • Instantiate(): Clones a prefab or object to create a new one
  • Destroy(): Removes an object from memory
  • Prefab: Reusable object template

1. Instantiate() - Creating Objects

Instantiate() clones a prefab or existing object to create a new object.

Basic Usage

using UnityEngine;

public class ArrowGenerator : MonoBehaviour
{
    // Arrow prefab (assign in Inspector)
    public GameObject arrowPrefab;
    
    void Update()
    {
        // Clone prefab to create new arrow
        GameObject newArrow = Instantiate(arrowPrefab);
    }
}

Creating at Specific Position

using UnityEngine;

public class ArrowGenerator : MonoBehaviour
{
    public GameObject arrowPrefab;
    
    void Update()
    {
        // Create arrow at specific position
        Vector3 spawnPosition = new Vector3(0, 6f, 0);
        GameObject newArrow = Instantiate(arrowPrefab, spawnPosition, Quaternion.identity);
    }
}

Creating at Random Position

using UnityEngine;

public class ArrowGenerator : MonoBehaviour
{
    public GameObject arrowPrefab;
    float spawnTime = 0.3f;
    float delta = 0f;

    void Update()
    {
        // Accumulate time
        delta += Time.deltaTime;
        
        // Create arrow after certain time
        if (delta > spawnTime)
        {
            delta = 0f;
            
            // Calculate random X position
            float randomX = Random.Range(-8.4f, 8.4f);
            
            // Create arrow at random position
            Vector3 spawnPosition = new Vector3(randomX, 6f, 0);
            GameObject newArrow = Instantiate(arrowPrefab, spawnPosition, Quaternion.identity);
        }
    }
}

Instantiate() Parameters

// 1. Prefab only (creates at current position)
GameObject obj = Instantiate(prefab);

// 2. With position
GameObject obj = Instantiate(prefab, position, rotation);

// 3. With parent
GameObject obj = Instantiate(prefab, parentTransform);

// 4. Position, rotation, and parent all specified
GameObject obj = Instantiate(prefab, position, rotation, parentTransform);

2. Destroy() - Destroying Objects

Destroy() removes an object from memory.

Basic Usage

using UnityEngine;

public class ArrowController : MonoBehaviour
{
    public float arrowSpeed = 0.1f;

    void Update()
    {
        // Move arrow down
        transform.Translate(0, -arrowSpeed, 0);

        // Check if off-screen
        if (transform.position.y < -6f)
        {
            // Destroy arrow
            Destroy(gameObject);
        }
    }
}

Destroying Other Objects

using UnityEngine;

public class EnemyController : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        // If collided object has "Bullet" tag
        if (other.CompareTag("Bullet"))
        {
            // Destroy bullet
            Destroy(other.gameObject);
            
            // Destroy self
            Destroy(gameObject);
        }
    }
}

Delayed Destruction

using UnityEngine;

public class Explosion : MonoBehaviour
{
    void Start()
    {
        // Destroy after 2 seconds
        Destroy(gameObject, 2f);
    }
}

Destroy() Parameters

// 1. Immediate destruction
Destroy(gameObject);

// 2. Delayed destruction (in seconds)
Destroy(gameObject, 2f);

// 3. Destroy component only (object remains)
Destroy(GetComponent<Rigidbody2D>());

3. Practical Examples

Example 1: Arrow Generator

using UnityEngine;

public class ArrowGenerator : MonoBehaviour
{
    public GameObject arrowPrefab;
    float spawnTime = 0.3f;
    float delta = 0f;

    void Update()
    {
        // Accumulate time
        delta += Time.deltaTime;
        
        // Create arrow after certain time
        if (delta > spawnTime)
        {
            // Reset timer
            delta = 0f;
            
            // Clone prefab to create arrow
            GameObject arrow = Instantiate(arrowPrefab);
            
            // Set random X position
            float randomX = Random.Range(-8.4f, 8.4f);
            arrow.transform.position = new Vector3(randomX, 6f, 0);
        }
    }
}

Example 2: Automatic Arrow Destruction

using UnityEngine;

public class ArrowController : MonoBehaviour
{
    public float arrowSpeed = 0.1f;

    void Update()
    {
        // Move arrow down
        transform.Translate(0, -arrowSpeed, 0);

        // Check if below screen
        if (transform.position.y < -6f)
        {
            // Destroy arrow
            Destroy(gameObject);
        }
    }
}

Example 3: Fireball Spawner

using UnityEngine;

public class FireballSpawner : MonoBehaviour
{
    public GameObject fireballPrefab;
    public float spawnHeight = 8f;
    public float minX = -5f;
    public float maxX = 5f;

    void Start()
    {
        // Start spawning fireballs
        StartCoroutine(SpawnFireballs());
    }

    System.Collections.IEnumerator SpawnFireballs()
    {
        for (int i = 0; i < 10; i++)
        {
            // Calculate random position
            float randomX = Random.Range(minX, maxX);
            Vector3 spawnPosition = new Vector3(randomX, spawnHeight, 0);
            
            // Create fireball
            GameObject fireball = Instantiate(fireballPrefab, spawnPosition, Quaternion.identity);
            fireball.SetActive(true);
            
            // Wait random time between 0.5 and 2 seconds
            float delay = Random.Range(0.5f, 2f);
            yield return new WaitForSeconds(delay);
        }
    }
}

4. Precautions

1. Null Check

void Update()
{
    // ✅ Safe way
    if (arrowPrefab != null)
    {
        GameObject arrow = Instantiate(arrowPrefab);
    }
}

2. Memory Management

// ❌ Bad example: Infinite creation
void Update()
{
    GameObject obj = Instantiate(prefab);
    // Memory leak if not destroyed
}

// ✅ Good example: Destroy appropriately after creation
void Update()
{
    GameObject obj = Instantiate(prefab);
    Destroy(obj, 5f); // Auto-destroy after 5 seconds
}

3. Destroy() Timing

void Update()
{
    // Destroy() doesn't execute immediately
    Destroy(gameObject);
    
    // ❌ Dangerous: Accessing destroyed object
    Debug.Log(gameObject.name); // May cause error
    
    // ✅ Safe: Return immediately
    Destroy(gameObject);
    return;
}

4. Prefab vs Instance

public GameObject arrowPrefab; // Prefab (original)

void Start()
{
    // Clone prefab to create instances
    GameObject arrow1 = Instantiate(arrowPrefab);
    GameObject arrow2 = Instantiate(arrowPrefab);
    
    // arrow1 and arrow2 are different objects
    // arrowPrefab is the original, don't modify it
}

5. Advanced Usage

Object Pooling

When creating/destroying many objects, object pooling is more efficient.

using UnityEngine;
using System.Collections.Generic;

public class ObjectPool : MonoBehaviour
{
    public GameObject prefab;
    public int poolSize = 10;
    private List<GameObject> pool = new List<GameObject>();

    void Start()
    {
        // Pre-create objects
        for (int i = 0; i < poolSize; i++)
        {
            GameObject obj = Instantiate(prefab);
            obj.SetActive(false);
            pool.Add(obj);
        }
    }

    // Get available object
    public GameObject GetObject()
    {
        foreach (GameObject obj in pool)
        {
            if (!obj.activeInHierarchy)
            {
                obj.SetActive(true);
                return obj;
            }
        }
        
        // If all in use, create new one
        GameObject newObj = Instantiate(prefab);
        pool.Add(newObj);
        return newObj;
    }

    // Return object (deactivate)
    public void ReturnObject(GameObject obj)
    {
        obj.SetActive(false);
    }
}

6. Summary

Instantiate()

  • Purpose: Clone prefab or object to create new one
  • Position: Instantiate(prefab, position, rotation)
  • Precautions: Null check required, memory management important

Destroy()

  • Purpose: Remove object from memory
  • Immediate: Destroy(gameObject)
  • Delayed: Destroy(gameObject, delay)
  • Precautions: Don't access after destruction

Best Practices

  1. Create only when needed: Unnecessary creation causes performance issues
  2. Destroy appropriately: Prevent memory leaks
  3. Use prefabs: Use prefabs for reusable objects
  4. Object pooling: Consider for frequently created/destroyed objects

Practice Problems

  1. Write a script that creates a bullet when spacebar is pressed.

  2. Write a script that automatically destroys objects that go off-screen.

  3. Write a script that creates a coin at a random position every second and automatically destroys it after 5 seconds.