모바일게임에서 재사용성이란 매우 중요하다.
만약 비행기 게임을 만들고 있다고 치자 총알이 초당 3번 나간다고 할때
총알을 Instantiate로 만들고 다쓴 총알을 Destroy로 삭제시킨다면
초당 3번의 메모리 할당이 일어나고 조금있다가 초당 3개의 Object가
가비지 컬렉터에 쌓일 것이다.
아무튼 이런 것을 해결하기 위해 Object Pool을 만들어보자
간단하게 설명하면 새로 만들거나 지우지 않고 미리 만들어둔
Object를 사용하는 개념이다.
GameObject는 여러가지가 있다. 타워에서부터
적, 총알, 효과(FX), 등등 모든 것을 Object Pool으로
만들어서 관리하는 것이 좋을 것이다.
종류에 상관없이 모든 Object를 한개의 Pool에 집어 넣어도 되지만
여기서는 각각 객체에 따라 다른 Pool을 사용하려고 한다.
이전에는 사용할 Object에서 Prefab에 대한 참조를 받아서
Instantiate를 했다. 이젠 PoolManager를 사용해서 해당 Prefab이
있는 Pool의 ID를 받아와서 객체를 받아가고자 한다.
여기서 ObjectPool을 dictionary로 관리하게 되는데 ID(string)으로
배열에 접근할 수 있는 컨테이너로 네임스페이스 generic 안에 있다.
ObjectPool은 다음과같은 알고리즘을 통하여 Pool 내에서
UnActivate 되어 있는 GameObject를 뱉어 낸다.
1. CurrentIndex가 가리키고 있는 Object가 UnActive라면
리턴한다. 이후 CurrentActive에 +1을 한다.
2. 만약 CurrentIndex의 Object가 Active 상태라면
Pool을 종주하면서 UnActive 되어 있는 Object를 찾는다.
3. 만약 종주 후에도 UnActive되어 있는 Object가 없다면
AddCount만큼 새로운 Object를 Instantiate를 하고
CurrentIndex를 새로만든 첫번째 Object로 옮긴다.
어짜피 게임을 하면서 Heap에 할당을 아예 안할 수 는 없다.
그렇다고 처음부터 엄청난 수의 메모리를 잡는 것도 이상하다.
이런 저런 생각끝에 만든 것으로 처음 예를들어 타워가 적은 초반에는
작은 사이즈의 Pool이 였다가 이후 타워가 많아지면
Pool의 사이즈가 커지는 것이 기본 아이디어 이다.
하지만 만약 반대로 초반 타워라면 많이 지었는데
후반에 타워들을 다 팔아버렸다면 문제가 생길 것이다.
따라서 4번째 알고리즘을 추가한다.
4. 일정 시간마다 Pool의 빈공간을 채크하다가
특정 타이밍(ex 스테이지 클리어)시 빈 공간이 많다고 생각되는
Pool의 크기를 줄인다.
이렇게 하면 유동적인 Object Pool 이 될 것이다.
테스트 영상은 다음과 같다. 많은 총알을 만들기 위해 총알을 느리게 했고
BulletPool의 상태를 간단한 코드를 통해 출력하도록 하였다.
타워는 아직 빌드하는 UI를 못만들어서 마우스를 클릭한 곳에 지어지도록 했다.