▼ BulletSpawner.cs
using UnityEngine;
/// <summary>
/// 마우스 클릭 시 오브젝트 풀에서 총알을 꺼내 쏘는 예시
/// </summary>
public class BulletSpawner : MonoBehaviour
{
// ObjectPool 스크립트 참조
public ObjectPool bulletPool;
// 발사 위치
public Transform firePoint;
// 총알 속도
public float bulletSpeed = 10f;
void Update()
{
// 마우스 왼쪽 버튼 클릭 시 발사
if (Input.GetMouseButtonDown(0))
{
// 풀에서 비활성화된 총알 하나 가져오기
GameObject bullet = bulletPool.GetObject();
// 총알을 발사 위치로 이동시킨 후 방향 초기화
bullet.transform.position = firePoint.position;
bullet.transform.rotation = firePoint.rotation;
// Rigidbody로 앞으로 힘을 준다
Rigidbody rb = bullet.GetComponent<Rigidbody>();
rb.velocity = firePoint.forward * bulletSpeed;
}
}
}
▼ Bullet.cs
using UnityEngine;
/// <summary>
/// 총알이 일정 시간 후 자동으로 풀에 반환되는 예시
/// </summary>
public class Bullet : MonoBehaviour
{
private ObjectPool pool;
private float lifetime = 3f; // 3초 뒤에 사라짐
void OnEnable()
{
// 활성화될 때마다 타이머 시작
Invoke(nameof(ReturnToPool), lifetime);
}
void OnDisable()
{
// 중복 호출 방지를 위해 타이머 초기화
CancelInvoke();
}
public void SetPool(ObjectPool objectPool)
{
pool = objectPool;
}
void ReturnToPool()
{
// 풀 매니저에게 자신을 반환
pool.ReturnObject(gameObject);
}
void OnCollisionEnter(Collision collision)
{
// 충돌 시에도 즉시 반환 가능
ReturnToPool();
}
}
▼ ObjectPool.cs
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 오브젝트 풀링을 담당하는 매니저 클래스
/// - Instantiate()와 Destroy()의 반복 호출을 피하기 위해
/// 미리 생성해둔 오브젝트를 재사용한다.
/// </summary>
public class ObjectPool : MonoBehaviour
{
// 풀링할 프리팹 (예: 총알 프리팹)
public GameObject prefab;
// 초기 생성할 오브젝트 개수
public int initialSize = 10;
// 실제로 풀에 저장될 리스트 (비활성화된 오브젝트들)
private List<GameObject> pool = new List<GameObject>();
void Awake()
{
// 게임 시작 시 초기 오브젝트 생성
for (int i = 0; i < initialSize; i++)
{
// 프리팹을 생성
GameObject obj = Instantiate(prefab);
// 풀 매니저의 자식으로 정리 (Hierarchy 깔끔하게)
obj.transform.SetParent(transform);
// 오브젝트를 비활성화해서 풀에 저장
obj.SetActive(false);
// 리스트에 추가
pool.Add(obj);
}
}
/// <summary>
/// 풀에서 사용 가능한 오브젝트를 꺼내서 반환
/// 없으면 새로 만들어서 반환한다.
/// </summary>
public GameObject GetObject()
{
// 비활성화된 오브젝트가 있는지 탐색
foreach (GameObject obj in pool)
{
if (!obj.activeInHierarchy)
{
// 비활성 상태면 사용 가능 → 활성화하고 반환
obj.SetActive(true);
return obj;
}
}
// 모두 사용 중이면 새 오브젝트 생성
GameObject newObj = Instantiate(prefab);
newObj.transform.SetParent(transform);
pool.Add(newObj);
return newObj;
}
/// <summary>
/// 사용이 끝난 오브젝트를 다시 풀로 반환
/// </summary>
public void ReturnObject(GameObject obj)
{
// 오브젝트를 비활성화시켜 재사용 대기
obj.SetActive(false);
}
}