• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    해결됨

버그를 찾아서 해결을 했는데 이해가 안됩니다

21.09.11 04:05 작성 조회수 241

0

안녕하세요!

 

강의를 따라하면서, 테스트를 해보는데 버그 2개를 찾아냈습니다

일단, 버그 발생 원인은 저의 오타 때문이었구요

그런데 그 버그 증상이 이해가 잘 가서 혹시 설명을 부탁드려도 될지 궁금해서요

 

첫번째 버그는 이렇습니다

ShotScriptEnemy.cs의 DestroyGameObject()에서 실수로 ObjectPoolManager.instance.playerShot.Create()를 넣어버렸습니다

적의 탄환이 아니라 플레이어의 탄환을 숨겨버리게 된거죠

증상이 좀 많이 황상한데요

플레이어로 탄환을 발사를 잘 하다가 어느 시점에 가면, 스페이스바를 누르면, 플레이어 우주선 바로 앞에(shotPosition) 적 탄환이 나타납니다

PlayerScript.cs에서 탄환 프리팹을 생성하고 PlayerShot.cs 접근을 하려는데 당연히 적 탄환이 생성되어 버렸으니 해당 스크립트가 없어서 NullReferenceException이 발생합니다

위의 오타를 발견하기 전까지 10번은 확인했는데 인스펙터에서 Player랑 Enemy들에 적용해준 프리펩들이 얽힌건 전혀 없더라고요

도대체 어떻게 전혀 상관도 없는 프리펩이 생성된건지 궁금합니다

 

두번째 버그는 이렇습니다

적들이 쏘는 탄환이 어느 순간부터 가끔씩, 왼쪽 끝에 도달 하기도 전에 사라집니다

버그의 원인은 PlayerScript.cs에서 적 탄환을 플레이어가 맞았을때, 그리고 EnemyShotScript.cs에서 적 탄환이 플레이어와 충돌 했을때 각각 한번씩, 총 두번 DestroyGameObeject()함수가 호출 됐더라고요

이건 제가 원인을 생각을 해봤는데

오브젝트 풀에, 적 탄환 a가 생성이 되고 화면 끝에 도달을 하건, 플레이어와 충돌을 하건해서 사라지게 됩니다

그런데 사라지게 하는 함수가 2번 호출 된거죠. 문제는 이 오브젝트가 사라지면서 SetActive(false)가 되는 겁니다

그래서 두번째 호출된게 나중에 a 탄환이 다시 나타날 때, 뒤 늦게 적용된게 아닐까요? 바로 사라지지 않는건...... 유니티의 작업 사이클 때문이고요

 

혹시 실험 해보시고 의견을 알려주실 수 있을까요?

답변 1

답변을 작성해보세요.

1

안녕하세요. 

이런 현상은 재현이 쉽지 않습니다. 오류라는 것이 약간씩 달라지면서 결과가 확연하게 달라지기 때문에요. 코드를 보내주시면 확인해보겠습니다.

그래도 우선은 생각나는 대로 말씀드리겠습니다. 

첫번째 버그를 생각해보면요. 저희가 원한 것이 풀을 가지고 Create 하는 부분과 Destroy 하는 부분이 정확하게 일어나야 코드가 동작을 하겠죠. 

그런데 오타가 나서 다른곳에서 Destroy 를 하거나 Create 를 하는 경우가 생기면 전체 프로그램 자체가 어긋나기 시작합니다.  이건 논리적인 오류에 속하므로 오류입니다. 

명심하셔야 하는게 Null Exception 은 한번 나면 그걸로 오류가 나서 게임이 종료되거나 죽었다고 생각하셔야 합니다. 잘 진행되는 것처럼 보여도 그것은 피씨에서 테스트할때 씬뷰에서 그렇게 동작하는 것처럼 보이는 것일 뿐이고요.  

게임을 만드는게 어려운게 오류가 없을수는 없지만 한번 오류가 나서 그걸  못잡으면 그 프로젝트는 더이상 손을 쓸수가 없게 됩니다. 거의 종료된다고 봐야죠. 

 

두번째 현상을 설명해보면요. 두번째 증상에서 총알이 없어지는 현상이 발생한 것을 보았을때 이미 다른곳에서 그것을 재사용하고 있기 때문에 그런 증상이 생긴 것입니다. 우선 하나씩 오류를 해결해가면서 짝을 맞춘다고 생각하시면서 적용을 해야 할 것 같습니다.  우선 총알이 어디서 Create 와 Destroy 를 하고 있는지 찾아보시는 것도 좋은 방법 같고요. 그 경우 틀림없이 짝이 안맞는 경우가 있을 것입니다. 이걸 해결해야 게임이 오류가 없어지겠죠. 프린트도 관계되는 부분에서 다 넣어보시고 살펴보시는 것도 좋고요. 디버그도 해보시는 것도 좋습니다. 

그리고 이것과 관계없이 오브젝트 풀을 쓰는 이유는 메모리를 사용함으로써 게임의 속도를 높이기 위해서입니다. 오류가 나서 처리가 안되면 다 걷어버리는게 맞습니다. 이전에 말씀드린 게임프로그램과 관련된 속도를 생각해보시는 것도 좋을 것 같습니다. 

오브젝트 풀이 오류 처리가 안되어 작업속도가 늦어지는 걸 생각해보면 차라리 게임이 느려지더라도 유니티의 Create 와 Destroy 를 사용하는 것이 맘이 편하니까요. 그리고 요즘에는 유니티도 폰사양도 더 좋아져서 Create Destroy 가 그렇게 문제가 되지는 않는 것 같습니다. 

(오브젝트 풀을 써야 할때는 적이 몇천 단위로 나오는데 게임이 느려진다 이럴때 오브젝트풀을 쓰는 것이 맞을 것 같습니다) 우선은 작은 게임을 여러 개 완료하는 것을 목표로 하는 것이 좋은 것 같습니다. 우선 강의에서 소개는 했으니 오류는 처리해야겠지만요 

감사합니다. 좋은 하루 되세요 ^^