[Unity] 오브젝트 재활용하기

PublicMinsu·2023년 12월 6일
0

개요


이전에 설명했듯 큐브를 이리저리 돌려보며 플레이하는 게임을 만들고자 했다.

큐브는 이 게임의 핵심적인 요소이다.
앞으로 사용될 큐브가 정확히 몇 개인지는 모르지만 많이 쓰이는 건 확실하다.

큐브는 생성(Instantiate)삭제(Destroy)의 과정을 반복할 것이다. 그 방법이 옳은 것일까?
논리적으로는 옳다. 당연히 만들고 부수고를 반복하는 게 맞지 않은가?

출처 : https://blog.unity.com/kr/games/optimize-your-mobile-game-performance-tips-on-profiling-memory-and-code-architecture-from

하지만 매 순간 만들고 부수는 것은 딱히 좋은 방법은 아니다. 똑같은 기능을 해줄 수 있다면 재활용하는 것도 답이다.

오브젝트 풀

행사장과 의자


행사가 자주 열린다고 해보자.
매 행사마다 의자를 폐기 처분하고 새로 사 오는 것은 낭비일 것이다.

창고에 집어넣고 필요할 때 꺼내는 것이 나을 것이다.
이것이 오브젝트 풀의 원리이다.

행사가 더 이상 열릴 필요가 없다고 생각해 보자.
그렇다면 의자가 창고에서 자리를 차지할 필요가 있을까?
행사가 다시 열리긴 하는데 그 주기가 가끔이라면?
의자가 창고에서 자리를 차지하고 있는 게 나을까? 의자 대신 다른 물건을 창고에 넣어두는 게 맞을까?

이것이 오브젝트 풀의 단점이다.

비유를 열심히 생각해서 작성해 봤지만 틀리게 전달될 것 같다는 생각이 들기도 하다.

오브젝트 풀이란

오브젝트 풀의 목적은 자주 쓰이는 오브젝트에 대해서 속도가 느리고 가비지 문제를 유발하는 Instantiate와 Destroy를 매 순간 하기보다는 비활성화, 활성화를 활용하여 오브젝트를 재사용해 주는 것이다.

오브젝트가 불필요할 때는 의자를 창고에 넣듯이 풀에 집어넣어 주고 필요할 때는 창고에서 의자를 꺼내듯 풀에서 오브젝트를 꺼내주는 것이다.

Unity에서의 ObjectPool

원래 ObjectPool은 큐, 스택 등의 자료구조를 활용하여 직접 만들어주었다.
풀의 오브젝트가 부족한 경우 Instantiate로 생성해 주는 등의 작업도 직접 작성해 줘야 했지만 이제 유니티에서 직접 ObjectPool을 제공해 준다.
유니티 ObjectPool을 사용하기 위해선 using UnityEngine.Pool;을 추가해 줘야 한다.
이후 원하는 타입의 오브젝트 풀을 선언해 준다.
유니티의 ObjectPool은 생성자에 집어넣는 값으로 상세한 조작을 할 수 있다.

createFunc은 오브젝트가 풀의 부족해서 생성할 때 사용할 함수
actionOnGet은 오브젝트를 풀에서 가져올 때 사용할 함수
actionOnRelease은 오브젝트를 풀에 집어넣을 때 사용할 함수
actionOnDestroy은 오브젝트가 최대 개수를 넘어서 삭제할 때 사용할 함수
collectionCheck은 오브젝트를 풀에 집어넣을 때 이미 집어넣은 오브젝트인지 확인 여부
defaultCapacity은 풀의 초기 오브젝트 개수
maxSize은 풀에 남겨둘 최대 오브젝트 개수 (해당 개수보다 많으면 삭제)
자세히는 : https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1-ctor.html

ObjectPool의 동작 중 Get을 살펴보면 생성자에서 추가해 준 대리자를 실행해 주는 것을 볼 수 있다. (m_CreateFunc, m_ActionOnGet)

하지만 보이듯이 풀의 오브젝트가 부족한 경우 Instantiate이 아닌 m_CreateFunc를 호출하기에 사용자가 직접 Instantiate와 같은 로직을 작성해 줘야 한다.

간단하게 작성해 주었다.
경우에 따라 내용을 추가해 줘도 좋다. (점수를 올려준다든지의 동작을 추가해 주면 어떨까 싶었다)

이후 작성한 함수들을 생성자 매개 변수에 채워주면 된다.

테스트

테스트는 코루틴을 활용하여 작성해봤다.

생성과 삭제 없이 활성화와 비활성화만 반복하는 것을 볼 수 있다.
원하는 대로 작동한 것이다.

단점에 대해서

의자 비유에서 오브젝트 풀의 단점에 대해서 말했을 것이다.
의자가 창고에 계속 남아있어야 하는지에 대해서 말이다.

오브젝트 풀이란 오브젝트를 생성해서 메모리에 할당해두는 것이다.
만약 자주 사용하지 않을 오브젝트라면 메모리에 할당해두는 것보단 필요할 때 할당하는 것이 효율적일 것이다.
당장 자주 사용하더라도 나중에 사용할 일이 없다면 할당을 해제해 줘야 할 것이다.

"어느 정도로 사용해야 자주인 것일까?"
"지금 내가 만들어야 할 오브젝트는 오브젝트 풀을 사용하는 것이 맞는 걸까?"

개발을 하다 보면 만날 수 있는 트레이드오프이다. 강철의 연금술사에서 팔 한 짝을 대가로 연성진 없이 연금술을 쓸 수 있듯 메모리를 차지하고 할당과 해제의 과정 없이 오브젝트를 재사용할 수 있게 되는 것이다.

오브젝트 풀을 사용할지, 사용한다면 최대 몇 개를 남겨둘지, 언제 Clear할지에 대해서는 개발자가 고민해야 할 요소이다.

profile
연락 : publicminsu@naver.com

0개의 댓글