🔔 유튜브 크리에이터 베르의 게임 개발 유튜브의 "오브젝트 풀링 구현하기 | 유니티" 를 보고 공부하여 작성한 게시글입니다! 🔔
오브젝트 풀링이란?
오브젝트가 많이 쌓이고, 제거가 된다면 가비지 컬렉터가 지나갈 때 많은 리소스 손실이 있을 수 있습니다.
따라서 리소스를 줄이기 위해, 오브젝트를 담아 놓을 수 있는 그릇을 만드는 최적화 기법입니다.
오브젝트 풀링을 만들면, 그 곳에서 오브젝트들을 꺼내고 쓰고를 반복하여 더욱 좋은 성능의 게임을 만들 수 있습니다.
이번에는 Bullet이라는 프리팹을 이용하는 경우만 만들어 보고, 이 후에는 다른 오브젝트도 넣을 수 있는 멀티 방법도 적용할 줄 알아야합니다.
🧷 1. 오브젝트 풀링
- Object Pool 스크립트
public class ObjectPool : MonoBehaviour
{
public static ObjectPool Instance;
[SerializeField]
private GameObject poolingObjectPrefab;
private Queue<Bullet> poolingObjectQueue = new Queue<Bullet>();
void Awake()
{
Instance = this;
Initialize(10);
}
private Bullet CreateNewObject()
{
var newObj = Instantiate(poolingObjectPrefab, transform).GetComponent<Bullet>();
newObj.gameObject.SetActive(false);
return newObj;
}
private void Initialize(int count)
{
for(int i = 0; i < count; i++)
{
poolingObjectQueue.Enqueue(CreateNewObject());
}
}
public static Bullet GetObject()
{
if(Instance.poolingObjectQueue.Count > 0)
{
var obj = Instance.poolingObjectQueue.Dequeue();
obj.transform.SetParent(null);
obj.gameObject.SetActive(true);
return obj;
}
else
{
var newObj = Instance.CreateNewObject();
newObj.transform.SetParent(null);
newObj.gameObject.SetActive(true);
return newObj;
}
}
public static void ReturnObject(Bullet bullet)
{
bullet.gameObject.SetActive(false);
bullet.transform.SetParent(Instance.transform);
Instance.poolingObjectQueue.Enqueue(bullet);
}
}
public static ObjectPool 이라는 한가지 기능만 사용 하는 싱글톤 기법을 사용합니다.
이 후 컨테이너는 Queue를 이용해 줍니다.
Initialize() : count만큼 오브젝트를 미리 생성 해 넣어 줍니다.
GetObject() : Queue에서 가져와 주는 것, 있으면 그대로 가져오고, 없으면 새로 생성하여 가져옵니다.
ReturnObject() : 오브젝트를 Queue 다시 넣어줍니다.
CreateNewObject() : 새로운 오브젝트를 생성 해줍니다.
🧷 2. 적용 해 보기
- Player 스크립트
public class Shooter : MonoBehaviour
{
[SerializeField]
private GameObject bulletPrefab;
private Camera mainCam;
void Start()
{
mainCam = Camera.main;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
RaycastHit hitResult;
if(Physics.Raycast(mainCam.ScreenPointToRay(Input.mousePosition), out hitResult))
{
var direction = new Vector3(hitResult.point.x, transform.position.y, hitResult.point.z) - transform.position;
var bullet = ObjectPool.GetObject();// Instantiate(bulletPrefab, transform.position + direction.normalized, Quaternion.identity).GetComponent<Bullet>();
bullet.transform.position = transform.position + direction.normalized;
bullet.Shoot(direction.normalized);
}
}
}
}
기존의 Bullet 생성 시의 Instantiate 함수 대신, ObjectPool.GetObject()를 통하여, 총알을 나눠주는 모습입니다.
- Bullet 스크립트
public class Bullet : MonoBehaviour
{
private Vector3 direction;
public void Shoot(Vector3 dir)
{
direction = dir;
//Destroy(gameObject, 5f);
Invoke("DestoryBullet", 5f);
}
private void DestoryBullet()
{
ObjectPool.ReturnObject(this);
}
void Update()
{
transform.Translate(direction);
}
}
기존의 오브젝트 파괴인 Destory() 기능 대신, ReturnObject를 통하여 회수하는 모습을 보여줍니다.
출처: 베르의 게임 개발님 유튜브
https://www.youtube.com/watch?v=xiojw0lHzro