본문 바로가기

유니티 게임 개발하기/2D 게임 개발일지

유니티 - 탄막 슈팅 게임을 만들자 (5), 프레임 드랍을 해결하기.

안녕하세요, 윈디입니다.


지난번에 탄 삭제를 하도록 만들때,  이벤트와 델리게이트를 사용해서 탄을 삭제하는 방법을 사용해서 탄을 한번에 삭제를 했었는데요,

그 이후 저는, 탄을 삭제하고 아이템으로 변한 탄들이 플레이어에게 점수로 들어가는 식으로 구현을 했었습니다.

이렇게 탄을 한 프레임에 모두 삭제를 하다보니까, 순간적으로 렉이 발생하더라구요.

이 렉을 해결하기 위해서는 당연히 정확한 원인을 파악해야겠죠?

유니티의 프로파일러를 돌려서 확인해 보았습니다.


프로파일러는 유니티의 Windows 메뉴에서 확인하실 수 있습니다. 단축키는 컨트롤+7 입니다.

프로파일러를 킨 상태로 게임을 실행하면 자동으로 Cpu 사용량이 기록이 됩니다.

그래서 보스를 죽이는 시점을 확인해 봤더니..이렇게 나왔습니다.


토탈 64퍼센트나 차지하는 것들이 있어서 쭉 찾아서 내려가 보니,

렉이 걸렸던 실제 요인은 이거였군요. 탄들이 전부 아이템으로 변하는 것이 문제가 아니라, 아이템이 플레이어에게 모이면서, 플레이어 및 다른 아이템들과 충돌하는 것들이 동시에 너무 많이 일어나서 충돌 연산이 한 프레임에서 처리하기 버거울 정도로 많아졌던 거였던 거네요.

문제를 명확하게 하니, 여러가지 해결책이 있었습니다. 일단, 동시에 일어나는 연산을 줄이기 위해서,

 아이템으로 변하는 타이밍을 0초~0.4초 이내에서 랜덤하게 설정해 기본적인 문제를 해결 했습니다.




또한, 아이템을 '먹는다' 라는 생각에 지금까지 플레이어 스크립트에서 아이템의 종류를 식별해서 아이템을 먹여주었고, 아이템 스크립트에서는 단순히 충돌체크를 해서 그리고 캐릭터 주변으로 갔을 때 플레이어가 흡수할 수 있도록 유도성을 띄도록 해주는 것만 스크립팅을 해 둔 상태였습니다. 및 삭제만 진행했었는데요, 그렇게 되니 플레이어에서 한번, 아이템에서 한번 총 두번의 충돌 함수가 발생하게 되었습니다.


이러한 비효율성을 해결하기 위해서 충돌 체크 및 아이템 삭제, 그리고 플레이어의 점수나 파워를 올려 주는 코드도 모두 아이템컨트롤 스크립트로 옮겨 담아서, 플레이어 쪽에선 아이템과의 충돌에 신경쓰지 않아도 되도록 만들었습니다.



위 스크립트를 읽으신 분들이라면 어? 하실수도 있을 것 같아요. 네, 프로파일러에서는 분명 OnCollisionStay2D였던 것이

CollisonEnter로 바뀌었지요.


사실 아이템 흡수는 CollsionStay를 이용해서 아이템이 계속 Absorber 의 범위 안에 있을때 플레이어를 따라가도록 구현한 것이었거든요. 하지만 이렇게 다중충돌이 일어나는 경우 매 프레임 계속 이벤트를 발생해야 하는 단점이 생겨서, 대신 코루틴으로 만들고  Absorber와 충돌하는 즉시 코루틴이 실행되어 플레이어를 따라가도록 하습니다.

이제 아이템과 플레이어가 충돌했을 때 실제로 발생하는 충돌연산은 아이템 하나당 한번밖에 발생하지 않으니, 사실상 연산에 많은 이득이 되겠네요.


이렇게 세가지를 변경하고 나니, 이제 다음과 같은 상황에서도 렉이 걸리지 않네요.



프로파일러도 확인해 보죠.



프로파일러에서는 전과 비교해서 하늘을 뚫었던 그래프가 살짝 넓어지면서

( 랜덤으로 준 시간의 영향인것 같네요. 부담을 주변에 분산해 준거죠.)

CPU 부담도 훨씬 덜어진 거 같습니다..


아무래도.. 역시 주변에 부담을 나눠주는 게 제일 효과가 컸던 모양이에요.

트리거 엔터로 바뀌면서 부담도 조금 더 줄기는 했지만요.