상세 컨텐츠

본문 제목

유니티 플레이메이커 오브젝트 풀링 object pooling

UNITY PlayMaker

by 오픈플레이 2019. 6. 29. 16:54

본문

게임을 할 땐 언제나 해당 게임오브젝트를 생성하고, 그 오브젝트의 역할을 다 했다면 기능을 꺼줘야 하죠.

보통 Instanciate (플레이메이커에서는 Create GameObject)와 Destroy 를 번갈아 쓰겠지만, Destroy를 사용할 시 메모리 처리 과정에서 지연시간이 일어나게 됩니다. 자주 쓸 시 프레임드랍이 일어나는 요소로 지목되기도 하지요.

이런 단점을 보완하기위해 오브젝트 풀링 기법을 사용해야 하는데, 오브젝트 풀링의 핵심은 바로 활성Activate과 비활성DeActivate, 그리고 초기화 이들 3가지로, 자원의 재활용을 의미합니다.

이번 편은 슈팅게임에서 활용할 수 있는 오브젝트 풀링을 플레이메이커에서 어떻게 만들지 알아보겠습니다.

 


1. 총알 bullet 만들기

우선 Cube나 다른 3D 오브젝트를 만든 다음 플레이메이커 FSM을 Add 합니다.

오브젝트가 시작하자마자 translate 액션을 통해 z 방향으로 움직이도록 하고, 1초 후에 다음 이벤트로 넘어갑니다.

다음 이벤트에는 총알을 비활성 시켜줍니다. 총알 설정은 이렇게 간단한 구조로 만듭니다.

프리펩으로 만들어서 많이 꺼내 쓸거니까요. 만든 총알은 프리펩 prefeb으로 저장합시다.

 


2. 오브젝트 풀링 매니저 만들기

 

총알 그룹을 위한 빈 게임 오브젝트를 만들어 주고 위치를 잡아줍시다.

총알을 부모로 두기 위해 'bulletGroup' 오브젝트를 생성.

 

그다음 오브젝트 풀링 매니저역할을 할 빈 게임오브젝트를 만들고 역시 플레이메이커 FSM을 Add 해줍니다.

여기서는 'managerObjPool'로 만들었습니다.

그 다음 프리펩으로 저장한 총알을 10개 정도 불러내어 배열에 집어넣는 과정을 살펴봅시다.

init 이벤트에서는 bulletGroup을 부모역할을 할 변수로 지정해 줍시다.
불러올 총알의 총량 int_bulletTotal은 10으로 초기화

 

두개의 int 변수를 대조.

불러올 총알의 개수를 정하기위해 두개의 변수를 준비합니다.

int_tempBullet : 현재 불러온 총알의 총 갯수

int_bulletTotal : 희망하는 총알의 총 갯수

Int Compare 를 통해 현재 불러온 총알의 총 개수가 희망하는 총알의 총 갯수가 동일할 경우 다음 이벤트로 넘어가고, 불러온 총알의 갯수가 부족하면 'create bullet' 이벤트로 넘어갑니다.

create bullet 액션 1

create bullet 액션에서는 프리펩으로 저장된 총알을 불러오고, 불러온 총알을 obj_bulletGroup의 자식으로 둔 다음, localPosition을 체크해줍니다. 이러면 총알은 자동으로 부모의 위치 (0, 0, 0)로 바뀝니다.

불러온 총알이 바로 나가면 안 되므로, Activate Game Object 액션을 통해 Activate 를 체크 해제하여, 총알을 비활성 시켜줍니다.

int_tempBullet +1 시켜주는 것을 잊지 않도록 합니다.

총알을 불러내었으므로 총알 1개가 처리되었다는 계산을 해줘야 합니다. Int Add 액션을 통해 앞서 만들었던 변수 int_tempBullet에 +1을 해주면 됩니다.

그렇다면 일단 실행을 해보죠.

10개의 총알이 불려 와 bulletGroup의 자식으로 두고 있고, 모두 비활성 된 것을 볼 수 있습니다.

 


3. 총알 발사

총알을 성공적으로 불러냈으니, 이제 쏴야겠죠. 여기서 본격적으로 활성과 비활성, 그리고 초기화 기능을 만들어야 합니다.

'stanby Shoot' 이벤트에서는 키 입력을 통해 다음 이벤트로 넘어가게 처리 합니다.
bulletGroup의 자식 'bullet'을 불러오고 비활성화 되어 있는지 체크합니다.

Get Next Child 액션은 말 그대로 자식 오브젝트를 차례로 선택을 합니다. Get Child를 쓸 경우 자식의 첫 번째만 선택되므로 유의하세요.

Game Objetct Is Visible 액션은 이 오브젝트가 보이는지 안 보이는지 리턴 값을 넘겨주는 액션입니다. 애석하게도, 플레이메이커에서는 C# 처럼 .enabled 함수가 없기때문에 대체 액션으로 사용했습니다. 원래는 '이 게임오브젝트가 활성화 / 비활성화 상태인가?'를 판별해야 하는데, 플레이메이커는 안보이더군요. 이 액션을 사용해도 무방합니다. 어쨋든 안보이는 상태이니까요.

a. 해당 오브젝트가 보이지 않을 경우 'shoot' 이벤트

 액션 'Get Key Up'은 나중에 설명하겠습니다.

우선 Active Game Object 액션으로 해당 오브젝트를 활성화해줍니다.

Set Position을 통해 총알을 왜 (0, 0, 0)으로 초기화해줬냐면, 이미 발사한 총알은 z 위치 어딘가에서 비활성화되었기 때문에 초기 발사위치인 bulletGroup내 로컬 포지션을 0으로 초기화해줘야 발사지점에서 다시 발사가 되어야 하기 때문이지요.

이벤트 마지막에는 float 변수 timeShootRate를 통해 발사 간격을 정해 둡니다. 0.1로 설정했으며,

0.1초 후에 다음 이벤트로 넘어가게 됩니다.

 

b. 해당 오브젝트가 보일 경우, 또는 활성화되어 있을 경우

'get bullet'이벤트에서 해당 총알이 보이냐 / 안 보이냐 처리를 한 이유는, 이미 날아가고 있는 총알에 대해 위치 초기화가 되지 않도록 만든 예외처리입니다.

이를 위해 단순히 timeShootRate를 통해 이벤트를 강제로 넘기고, 비활성화된 총알을 찾을 때까지 반복하도록 만들었습니다.

 


4. 연속 발사 처리

앞서 보여드렸듯이 키 입력을 받기 전 까지는 총알 발사 처리가 되지 않습니다.

키를 누르고 있으면 발사를 계속하고 키를 떼면 발사를 멈추게 하고 싶은데, 키 입력을 해제할 타이밍을 어디에 둘 것인가가 중요합니다.

총알이 발사되는 동안 'get bullet' -> 'shoot' -> 'cancel shoot', 그리고 키 입력이 계속되면 반복이 되죠.

이 반복은 빠르게 일어나기 때문에 'shoot' 과 'get other bullets' 이벤트 둘 다 키 해제 액션을 둬야 총알 발사 취소를 빠르게 할 수 있습니다.

총알을 연속으로 발사하고 싶으면 wait 액션을 통해 일정 시간이 지나면 강제로 FINISHED 이벤트로 넘어가게 됩니다.

이렇게 해서 키를 떼지 않는 한 총알이 연속으로 발사하게 만들었습니다.

'shoot' 이벤트 : Get Key Up 액션을 이벤트 맨 처음 둔 이유가 있습니다.

 

'get other bullets' 이벤트 : 여기서도 Get Key Up을 통해 키를 떼면 발사를 중지합니다.

 

끝으로 유튜브 영상본을 올립니다. 영상을 한번 보신 후 작업하시길 권합니다.

감사합니다.

관련글 더보기

댓글 영역