새소식

💻 Programming (프로그래밍)/Unity | C#

[Unity][C#] 오브젝트 풀링(Object Pooling) 최적화 기법

  • -

🔔 유튜브 크리에이터 베르의 게임 개발 유튜브의 "오브젝트 풀링 구현하기 | 유니티" 를 보고 공부하여 작성한 게시글입니다! 🔔

 

오브젝트가 많이 쌓이고, 제거가 된다면 가비지 컬렉터가 지나갈 때 많은 리소스 손실이 있을 수 있습니다.

따라서 리소스를 줄이기 위해, 오브젝트를 담아 놓을 수 있는 그릇을 만드는 최적화 기법입니다.

 

오브젝트 풀링을 만들면, 그 곳에서 오브젝트들을 꺼내고 쓰고를 반복하여 더욱 좋은 성능의 게임을 만들 수 있습니다.

 

이번에는 Bullet이라는 프리팹을 이용하는 경우만 만들어 보고, 이 후에는 다른 오브젝트도 넣을 수 있는 멀티 방법도 적용할 줄 알아야합니다.


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() : 새로운 오브젝트를 생성 해줍니다.


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()를 통하여, 총알을 나눠주는 모습입니다.

 

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 

 

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.