-
으엉 내일 발표날입니다!
왜 제가 발표자인지는 네이버 사다리타기가 알려줄거지만 말을 못하니.. ㅠ
내일 발표를 하기 전에 우선 완성은 했고, 발표 준비를하기 전에 복기하기 위해서 트러블 슈팅에 관해서 적어보도록 하겠습니다.
1. Visual Studio 버그?
GameManager 담당이 되어서 처음에 어떤걸 해야할지 막막했습니다. 팀원분들이 MainCharacter, UI, Enemy 담당을 하셔서 Git Desktop에서 Merge할 때 Conflict나지 않도록 하는 것이 중요합니다. 그래서 어떻게 해결할지 고민하다가 먼저 사용할 Scene에서 기본적으로 사용될 GameManager, MainCharacter, UI 등의 베이스를 만들었고, 충돌이 잘 일어나지 않는 Scripts 쪽을 하기로 결정했습니다.
MainCharacter와 Enemy가 체력과 스피드를 가지고 있기 때문에 같이 쓸 수 있도록 StatsSettingController.cs를 만들어주었습니다. 그런데 어느 순간 사용을 할 수 없다고 나오게 되었습니다.
계속 작업하면서 Merge했기 때문에 정확한 이유는 모르겠지만 갑자기 사용할 수 없어졌기 때문에 원인을 알기 위해서 튜터님을 찾아갔습니다.
제가 원인을 모르니깐 고칠 방법도 모르겠고 어떻게 검색을 해야하는지도 모르겠어서 튜터님을 찾아가게되었는데요.
원인은 Visual Studio 오른쪽에 있는 솔루션 탐색기 부분에서 사용하고 있던 cs 연결이 끊겼던 것이였습니다. Unity에는 정상적으로 있었는데 말이죠.
해결하기 위해서 솔루션 탐색기에서 '솔루션 빌드'를 해주면서 연결해보려고 했습니다만 연결이 되지 않아서 결국 고치지 못했습니다. 그렇다고 다른 cs가 연결이 끊기거나 새로 만든 cs 파일이 솔루션 탐색기에 들어가지 않거나 하지는 않아서 끊긴 script는 삭제하고 다시 StatsSettingController.cs를 생성해줬습니다.
그랬더니 똑같은 일이 발생했습니다. 또 끊기고 솔루션 빌드를 해줘도 연결이 되지 않아서 StatsSettingController 이름을 사용하지 않고 다른 이름으로 바꿔서 사용하게 되었습니다.
완벽한 해결 방법은 아니긴하지만 버그는 이용자가 고치기 힘들기 때문에.. 그리고 프로젝트 만드는 시간이 한정되어있기 때문에 이 현상을 고치기 위해서 시간을 쏟는 것은 좋지 못하다 판단해서 우회하기로 했습니다.
2. while
Main Character와 Enemy가 서로 충돌했을 때 Main Character의 체력이 감소하도록 만들었습니다.
여기서 문제는 Main Character와 Enemy의 충돌이 지속되었을 때 일정 시간의 텀을 두어서 체력이 감소하도록 만들려고 했습니다.
OnCollisionEnter2D는 부딪혔을 때 한 번만 실행이되며,
OnCollisionStay2D는 부딪힌 상태가 지속되면 실행되며,
OnCollisionExit2D는 부딪힌 상태가 끝나면 실행되는 함수입니다.
이것을 이용해서 Main Character의 체력이 감소하는 함수를 Enter2D에서는 그냥 사용하고 Stay2D에서는 Invoke와 while(true)를 이용하고 Exit2D는 break를 이용해서 멈추게 하려고 했습니다만, 게임이 멈췄습니다.
튜터님께 여쭤본 결과 제가 while문에 대해서 착각하고 있던게 있었습니다.
for문과 마찬가지로 while 또한 while 안에 있는 내용을 수행하고 난 뒤에 조건을 확인해서 다시 실행되거나 실행이 되지 않거나 라고 생각했지만
while은 안에 있는 내용을 수행하지 않고 while이 끝나면 수행되도록 쌓아두고 while이 끝나면 수행하는 것이었습니다.
그렇기 때문에 무한루프에 빠져 그 무엇도 실행이 되지 않고 쌓이고 있었으며, 무한 루프가 아닐 경우에는 체력이 한번에 쭉 감소하게 되었습니다.
이를 해결하기 위해서 코루틴을 사용해줬습니다.
코루틴에서 사용되는 yield return은 다른 함수들과 달리 while문 안에서 직접 실행되는 것으로 new WaitForSeconds()를 이용해서 while문이 실행되는 것을 딜레이 시켜줄 수 있습니다.
코루틴을 사용하기 위해서는 함수의 변수 타입은 IEnumerator이고, yield return을 꼭 써줘야합니다. 단, yield return을 사용할 수 있는 횟수는 지정되어 있지 않습니다.
protected IEnumerator AttackPlayer() { while (true) { CollisionEnemyToPlayer(); yield return delay; } } private void OnCollisionEnter2D(Collision2D collision) { if (collision.transform.tag == "Player") { StartCoroutine(AttackPlayer()); } } private void OnCollisionExit2D(Collision2D collision) { if (collision.transform.tag == "Player") { StopAllCoroutines(); } }
코루틴을 실행하기 위해서는 StartCoroutine
실행되고 있는 모든 코루틴을 멈추는 것은 StopAllCoroutines 입니다.
생성한 코루틴은 무한 루프이기 때문에 처음 부딪혔을 때 실행되도록 설정했으며, 부딪히는 상황이 끝날 때 실행되는 코루틴을 멈추도록 했습니다.
이렇게하면 한 번만 부딪혔을 때는 체력이 감소가 한번 일어나고 바로 코루틴이 멈추게 되며, 계속 부딪히고 있을 경우 무한 루프로 인해 코루틴이 멈추지 않아 체력이 계속 감소하게 되며 부딪히는 것이 끝나면 멈추게 됩니다.
3. 같은 클래스를 사용할 때 잊지 말아야할 것
게임을 제작할 때 랜덤 위치에 스폰되도록 설정한 것이 두가지가 있습니다.
하나는 Enemy고 하나는 Feed입니다.
Feed는 캐릭터의 체력을 채워주는 GameObject로 원래 기획은 Feed의 갯수가 일정하게 유지되도록 하는 것이었습니다.
사실 앞으로 작성할 이 부분을 해결하고 만들려고 했지만 생성이 되지 않아서 다르게 바꿨습니다.
그렇기 때문에 SpawnPointController.cs에서 Enemy와 Feed를 둘 다 관리하려고 했습니다.
Start에서 transform.tag를 통해서 Enemy와 Feed 스폰 함수를 분류했고 잘 작동했습니다.
문제는 Feed의 갯수를 유지하기 위해서 Update에 Feed 생성 함수를 사용했으며.. 그 어떤 조건을 주지 않았기 때문에 Enemy를 스폰할 때에도 Update가 작동되어서 Feed 생성 함수가 실행된다는 것을 인지하지 않고 사용했다는 것 입니다.
그래서 게임을 실행하게 되면 Enemy 스폰 갯수가 두배가 되서 생성이 되며 반은 Feed Object 하위에 생성되었습니다.
위에서 썼던 대로 해결방법에 Update에 조건을 줘서 조건에 맞다면 Feed 생성 함수가 작동되록 하면 됩니다.
하지만 원인이 뭐였는지 모르겠어서 그냥 Feed Spawn Script를 새로 작성해서 만들어주었습니다.
그리고 Update를 통해서 갯수를 유지해주려고 했는데 안되더라구요..
우회하긴 했지만 생성되어있는 모든 먹이를 먹을 경우 또 다른 엔딩이 나올 수 있도록 설정해줬습니다.
우선 크게 생각난 것은 3가지 입니다.
아무래도 정신없이 만들고 사실 금요일에 만들던거 엎었더니.. 생각이 잘 안나기도 합니다..
트러블 슈팅이 가장 중요하기 때문에 다음부터는 발생하면 좀 적어둬야겠습니다.