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
- Create only when needed: Unnecessary creation causes performance issues
- Destroy appropriately: Prevent memory leaks
- Use prefabs: Use prefabs for reusable objects
- Object pooling: Consider for frequently created/destroyed objects
Practice Problems
-
Write a script that creates a bullet when spacebar is pressed.
-
Write a script that automatically destroys objects that go off-screen.
-
Write a script that creates a coin at a random position every second and automatically destroys it after 5 seconds.