게임 개발에 널리 사용되는 테크닉으로, 게임의 성능을 개선하기 위해 사용한다.
Global 폴더에 ObjectPool.cs를 생성하자!
public class ObjectPool : MonoBehaviour
{
[System.Serializable]
public struct Pool
{
public string tag;
public GameObject prefab;
public int size;
}
public List<Pool> pools; // Pool에 대한 리스트
public Dictionary<string, Queue<GameObject>> poolDictionary;
private void Awake()
{
poolDictionary = new Dictionary<string, Queue<GameObject>>(); // poolDictionary 생성
foreach (var pool in pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
// 위에서 정해 놓은 pool의 사이즈만큼 미리 캐싱하기
for(int i =0; i < pool.size; i++)
{
GameObject obj = Instantiate(pool.prefab); // pool에 있는 prefab을 생성
obj.SetActive(false);
objectPool.Enqueue(obj);
}
poolDictionary.Add(pool.tag, objectPool); // 특정 tag에 대한 프리팹을 사이즈만큼 미리 가지고 있는 것.
}
}
// 풀에서 가져오기
public GameObject SpawnFromPool(string tag)
{
if(!poolDictionary.ContainsKey(tag)) return null;
// 오브젝트 풀에서 프리팹 꺼내기
GameObject obj = poolDictionary[tag].Dequeue();
// 꺼낸 프리팹을 다시 오브젝트 풀에 넣기
poolDictionary[tag].Enqueue(obj); // 꺼낸 프리팹을 다시 오브젝트 풀에 넣어 재사용한다.
return obj;
}
}
이제 이 오브젝트 풀을 ProjectileManager에게 추가해주자.
그리고 풀에 Arrow를 추가한다.
이후 ProjectileManager에서 코드를 수정한다. 기존에 있던 testObject를 변경해준다.
public class ProjectileManager : MonoBehaviour
{
[SerializeField] private ParticleSystem _impactParticleSystem;
public static ProjectileManager instance;
private ObjectPool objectPool; // 오브젝트 풀
public void Awake()
{
instance = this;
}
void Start()
{
// 오브젝트 풀 가져오기
objectPool = GetComponent<ObjectPool>();
}
public void ShootBullet(Vector2 startPosition, Vector2 direction, RangedAttackData attackData)
{
GameObject obj = objectPool.SpawnFromPool(attackData.bulletNameTag);
obj.transform.position = startPosition;
// 발사되는 코드
RangedAttackController attackController = obj.GetComponent<RangedAttackController>();
attackController.InitializeAttack(direction, attackData, this);
obj.SetActive(true);
}
}
해당 코드로 인해 bulletNameTag가 Object Pool에 등록되어 있는 것을 가져와 생성하게 된다.
Arrow가 20개가 미리 생성되어 있고 큐를 돌며 계속해서 재사용이 되는 것 까지 확인할 수 있다.