[게임만들기 ③] 1인 게임 개발에 한 번 도전해보았습니다 - 중간 점검 및 기획 수정편

기획기사 | 윤서호 기자 | 댓글: 5개 |



"배경 작업 하시는 것 아니었나요?"

저번에 배경 작업을 어떻게 할지, 에셋 스토어에 관련해서 언급한다고 말씀드렸습니다. 실제로 지금도 작업 중에 있지만, 그것보다는 지금 제가 봉착해있는 문제를 한 번은 언급해두는 것이 좋을 것 같다는 생각이 들었습니다. 사실 게임 개발이라는 것이 처음부터 모든 것이 순탄하게 진행되는 것이 아니고, 각 단계에서 봉착하는 문제를 하나하나 풀어가는 과정이니까요.

종종 사람 일이 말하는 대로 됐으면 얼마나 좋을까, 싶을 때가 많습니다. 물론 그렇게 생각할 때는 거의 대부분, 자신이 말한 대로 되지 않아서 답답함을 토로하는 때죠.

물론 게임 장르마다, 혹은 개발자의 능력에 따라 각자가 겪게 되는 문제는 제각각 다릅니다. 제 경우를 간단하게 말씀드리자면 1) (퀄리티는 보장할 순 없지만) 캐릭터 및 세계관, 시놉시스는 만들 수 있다. 2) 배경은 컨셉은 생각해낼 수 있지만 그림은 못 그린다 3) 프로그래밍은 기초는 알지만, 직접 코드를 짜지는 못한다. 4) 스테이지를 실제로 만들어본 경험은 없다. 이런 정도로 요약이 가능합니다.

즉 캐릭터 제작 단계가 지나고 나면, 문제가 산더미처럼 쌓일 것이 이미 예견되어있는 수순이었습니다. 이 부분은 저도 짐작은 하고 있었지만, 제가 본 것은 정말 말 그대로 빙산의 일각이었죠. 심지어 캐릭터 제작 단계에서부터 여러 가지 놓치고 있었다는 것도 다음 단계에 와서야 알게 됐습니다. 이를 깨닫게 된 건, 배경 및 에셋에 대한 조언을 구하기 위해서 유니티에 방문했을 때였죠.



▲ 유니티 오지현 에반젤리스트



■ 본을 활용한 2D 스프라이트 애니메이션 만들기



▲ 오지현 에반젤리스트(우): "왜 저장을 New Unity Project라고..." 저(좌) : "....실수로요"

사실 유니티에 방문하게 된 이유는 에셋 스토어에 대한 것과, 효과적인 디버깅 방법에 대해서 조언을 구하기 위해서였습니다. 유니티 에셋 스토어에는 상당히 많은 자료들이 있지만, 그렇기 때문에 제가 꼭 필요한 자료를 콕 집어서 찾기가 어려웠죠.

"이거 포토샵으로 하신 거에요? 굉장히 번거로우셨겠네요."

처음에 오지현 에반젤리스트를 만나서 제 프로젝트를 보여줬을 때 들었던 말입니다. 제가 기존에 알던 방식은, 따로따로 만들어둔 스프라이트를 미리 조립해서 프레임별로 쓰일 스프라이트 이미지들을 만들어낸 뒤, 이를 프레임에 맞게 배치하는 방식이었습니다.



▲ 포토샵으로 미리 만들어둔 스프라이트들을



▲ 엔진에 다 옮겨둔 다음에 재배치하면



▲ 애니메이션이 나오게 됩니다

그렇지만 이런 방식이 갖고 있는 치명적인 문제를 나중에 가서야 알게 됐죠. 무협에서 검술의 가장 높은 경지를 두고 '검신일체', 즉 검과 몸이 하나가 된다고 일컫잖아요? 그렇지만 게임 속에서 이렇게 검과 캐릭터의 구분없이 만들어두면 여러 가지 문제가 발생합니다.

여타 게임에서 그렇듯, 적이 무기에 닿으면 유저가 공격하는 판정이 나와야 합니다. 무기가 아닌 캐릭터가 적과 접촉하면 보통의 플랫포머에서는 피격 판정이 뜨게 되죠. 설령 적이 공격 액션을 취하지 않더라도 말이죠. 이를 프로그래밍에서는 보통 함수를 호출한다, 이런 식으로 말합니다. 어쨌든 이 각각 다른 함수를 호출하기 위해서는 검과 캐릭터에 각각 다른 조건을 줘야 합니다. 그 다른 조건을 주기 위해서는 스프라이트 단계에서부터 미리 나눠두는 게 편합니다. 그래야 따로따로 만들고, 나중에 종속시켜서 같이 움직이도록 할 수 있거든요.



▲ 이렇게 처음부터 하나로 묶어버리게 되면, 나중에 검과 캐릭터에 판정을 따로 주기가 어렵습니다

오지현 에반젤리스트가 제시한 솔루션은 아니마 2D라는 툴이었습니다. 유니티에서 무료로 제공하는 툴로, 스프라이트 메시와 본을 활용해서 마치 3D에서 본 애니메이션을 만드는 것처럼 작업할 수 있게 해주는 툴입니다.

엄밀히 말하면 3D 애니메이션도 2D 애니메이션과 기본은 같습니다. 각 프레임마다 키라는 것을 걸고, 그 키마다 자신이 원하는 이미지 혹은 동작을 입력하는 방식이죠. 3D 애니메이션에는 여기에 더 나아가서 본이라는 개념이 등장합니다. 말 그대로 뼈대를 모델링 안쪽에 심어두고, 뼈대를 움직여서 해당 3D 모델링을 더 쉽게 움직일 수 있도록 한 것이죠. 그렇게 하지 않으면 버텍스나 라인, 면, 폴리곤 등을 지정해서 움직여야 하는데, 일반적으로 인체 모델링에 사용되는 폴리곤 수는 최소 만 개 이상입니다. 그것들을 복잡하게 움직이기보다는, 뼈대로 큼직하게 묶어서 움직이는 것이 훨씬 편한 방법이죠.




이미 스프라이트는 각 부위별로 나누어놨기 때문에, 이를 스프라이트 메시로 변환하고 뼈대를 입히는 작업을 거쳤습니다. 우선 프로젝트 내에 스프라이트들을 따로 저장해두고, 스프라이트 메시를 hierarchy 창에다가 만든 뒤에 그 스프라이트를 넣어버렸습니다. 그리고는 본을 하나하나 만들고, 각 부위별로 바인딩을 했습니다.



▲ 본과 스프라이트 메시를 만들고



▲ 이를 각 파트에 맞게 바인드시켜나갔습니다

본을 만들 때 주의할 점은, 동작의 중심이 되는 몸통을 가장 상위에 두어야 합니다. 그리고 어깨->팔->손 이런 순으로 부모-자식 관계를 설정해두는 것이죠. 그렇게 하면 어깨를 움직일 때 팔, 손이 같이 움직이고 몸통을 움직일 때 어깨가 같이 움직이게 됩니다. 몸통, 어깨, 팔, 손을 각각 움직일 필요가 없는 것이죠. 다만 이 관계가 잘못 설정되면 손이 움직일 때 팔, 어깨가 같이 움직여버리거나 하기 때문에 이 부분을 유의할 필요가 있습니다.

유니티에서 애니메이션을 만드는 방법은 우선 Window창에서 Animation창을 활성화한 뒤에, Animation창 왼쪽 위에 있는 'Create New Clip'을 눌러서 클립을 만드는 것부터 시작합니다. 그런 뒤에는 녹화 버튼을 누르고, 각 프레임을 설정한 뒤에 그 프레임에 맞는 동작을 하나하나 만들어가는 것이죠. 작업이 다 끝났을 때는 녹화 버튼을 다시 한 번 눌러주면 완료됩니다.

각 조건에 맞게 애니메이션이 이어지도록 하려면 우선 Window창에서 Animator창을 연 뒤, 각 애니메이션 클립을 우클릭한 뒤에 Make a Transition이라는 창을 열어서 연결합니다. 그리고는 Transition에 조건을 입력하는 방식이죠. 조건은 Animator창에 있는 parameter에 입력하게 되는데, 이 부분은 스크립트, 즉 미리 입력해둔 코드와 연결이 되기 때문에 자세한 부분은 다음에 프로그래밍 과정에서 언급하도록 하겠습니다.



▲ 애니메이션 클립을 만들게 되면 애니메이터 창에 뜨게 되고, 이를 Transition으로 연결해나가게 되죠

여기에서는 Transition이 연결이 돼야 어느 한 동작에서 다음 동작으로 이어진다는 것, 어느 한 동작을 초기 상태로 만들어두고 싶다면 Animator창에서 해당 클립을 우클릭한 뒤에 Default 상태로 만들어두면 된다는 것 정도만 짧게 덧붙이고 넘어가겠습니다.



■ 에셋 스토어에 있는 에셋, 마음대로 써도 될까요?

프로그래밍을 못하는 사람들도 게임을 만드는 방법은 존재합니다. 흔히 알만툴이라고 부르는 RPG 만들기 같은 툴을 사용하는 것이죠. 알만툴 게임하면 단조로운 그래픽과 해상도, 고전적인 연출, 거기에 RPG만 만들 수 있는 툴이라는 편견이 있기도 하지만, 이 툴을 어떻게 활용하느냐에 따라서 다양한 게임을 만들어낼 수 있기도 합니다.

이와 유사하게 유니티 엔진 내에서도 기본적인 구성이 다 갖춰진 2D 게임킷이나 3D 게임킷 등을 제공합니다. 그뿐만 아니라 에셋스토어에는 다른 사람들이 만들어둔 게임킷을 구입해서 사용할 수 있기도 하죠.



▲ 툴킷 외에도 실습용으로 준비된 에셋이나 스크립트 등도 존재합니다

오지현 에반젤리스트가 제시한 솔루션은 이처럼 킷을 사용해서 제작하는 것이었습니다. 프로그래밍을 모르는 상태에서 게임을 만드는 가장 쉬운 방법이었기 때문이죠. 그리고 게임에 들어가는 요소 하나하나를 빠르게 훑어볼 수 있는 방법이기도 했습니다. 코딩이 필요해서 시간이 걸리는 부분들도, 코딩 없이 빠르게 추가하거나 빼보거나 할 수 있었으니까요.

물론 이 부분은 결국 받아들이지 않았습니다. 제 개인적인 이유로는 킷을 활용해서 만드는 것이 온전히 자기 게임인가, 하는 의문도 있었습니다. 또 다른 이유로는 킷을 활용하면, 다른 사람이 미리 작성해둔 틀 안에서만 작업이 가능합니다. 이는 넓게 보면 상용 엔지도 마찬가지긴 합니다. 그래서 몇몇 게임은 자체 엔진으로 제작하기도 하죠. 엔진마저도 그런데, 그보다 더 제한되어있는 킷이라고 하면 더 제약이 심할 거라는 생각이 들었죠.

또 킷을 사용하게 되면 해당 킷에 대한 정보를 새로 배워야 한다는 것도 문제였습니다. 이 부분은 RPG 만들기나, 스타크래프트 혹은 워크래프트의 유즈맵을 떠올려보면 됩니다. 분명 코딩을 짜지는 않지만, 스타크래프트1 유즈맵에는 컨디션과 트리거라는 것이 존재합니다. 어떤 조건에 어떤 명령, 혹은 어떤 상황이 일어난다는 것을 입력하는 것이죠. 2D게임킷 등은 좀 더 쉽게 구성이 되어있었지만, 그래도 툴킷을 어떻게 쓰는지 튜토리얼을 보고 새로 익힐 필요가 있었죠.



▲ 스타크래프트 유즈맵에서 가장 골치 아픈 부분이었던 Trigger(출처: 팀 리퀴드)

에셋 스토어에 있는 것을 조합해서 만드는 것이 자기 게임을 만드는 일인가? 라고 하는 부분은 사실 복잡하고, 또 어떻게 보면 민감한 문제일 수 있습니다. 순수 자기 창작의 범위가 어디까지인가, 하는 논쟁까지 이어질 수 있는 부분이기 때문이죠. 다만 유니티에서는 에셋 스토어에 있는 모든 에셋은 상용 게임에도 사용 가능하다고 밝혔습니다. 상업적 용도로도 사용이 가능하다는 것이죠. 사실 생각해보면 저도 제 자신의 게임을 만들기 위해서 부족한 부분은 에셋 스토어에서 구하려고 했으니, 처음 생각은 모순 그 자체였습니다. 그것이 어디까지 용납이 될까, 하는 부분은 개인차가 있을지 모릅니다. 적어도 유니티 에셋 스토어에 올라온 에셋들은, 상업적으로 써도 무방하다는 것은 확인했죠.

그 외에도 오픈소스를 공유하는 사이트들도 몇 곳이 존재합니다. 다만 그 소스들의 경우 상업적인 목표로 활용하고자 할 때는 라이센스에 대한 공지를 미리 확인해두는 것이 좋습니다. 일부에서는 상업적인 사용을 금지하는 경우도 있기 때문이죠.

에셋스토어에서 또 한 가지 유의할 것은, '킷'이 붙은 것들은 일반적으로 툴킷을 의미합니다. 즉 앞서 말한 2D 게임킷 같은 그런 종류인 것이죠. 더 쉽게 게임을 만들 수 있지만, 사전에 미리 제작한 틀 안에서만 활용이 가능한 경우가 많기 때문에 이 부분은 유의해야 합니다.



■ 코드 오류 문제를 잡으려면? - 디버깅




"여기저기에서 코드를 긁어모으긴 했는데, 오류가 났어요. 그런데 어디서 오류가 났는지 모르겠어요."

프로그래밍에 대해서 잘 모르는 분들이 아마 게임을 만들면서 숱하게 겪게 되는 부분입니다. 자신이 코드를 짤 수 없기 때문에, 이미 만들어진 코드를 갖고 와서 수치를 손보거나 하는 식으로 만들게 되거든요.

유니티를 찾아간 또 다른 목적은, 제가 여기저기에서 긁어 모은 코드가 오류가 났기 때문에 이를 해결하러 간 것도 있습니다. 정확히는 디버깅을 하는 방법을 배우기 위해서였죠. 여기저기에서 소스 코드를 긁어모으게 되면, 서로 안 맞아서 오류가 발생하는 경우가 많이 생기게 됩니다. 그때 어느 부분이 오류가 났는지 알아야 빠르게 수정할 수 있죠.

저는 적이 플레이어를 인식하면 공격 애니메이션을 취하도록 코드를 여기저기에서 긁어왔습니다. 우선 주인공 유채림의 움직임에 관련된 스크립트인 ChaerimController는 유니티 자습서 중 Creating a Basic Platformer Game의 컨트롤러 스크립트를 활용했습니다. 유채림의 체력과 적의 공격 판정을 만들기 위해서는 유니티 자습서 Survival Shooter에 예시로 나온 PlayerHealth스크립트와 Enemy Attack코드를 참조했죠.



▲ 지금 와서 생각해보면, 원래 3D용으로 고려한 코드들일 텐데 잘 돌아가는 게 신기합니다

각각의 코드는 잘 돌아가는 듯했습니다. 어쨌든 주인공 채림은 움직였고, 적도 잘 움직이긴 했습니다. 애니메이터로 트리거 세팅을 체크해봐도 Attack트리거에서 정상으로 적이 공격을 했죠. 다만 문제는 플레이어와 충돌할 때 공격하도록 코드를 짰는데, 이 부분이 잘 작동되지 않았던 것입니다.

이 상황에서 어떤 부분이 문제가 되는지 확인해보려면 디버그 테스트를 해야 합니다. 제가 아는 것은 Debug.Log()를 활용하는 방식이었는데, 그걸 일일히 하는 것은 상당히 비효율적이었죠. 그래서 배운 방식이 F9를 눌러서 해당 구문에 브레이크를 걸고, 비주얼 스튜디오를 유니티에 연결하면서 찾아가는 방식이었습니다.



▲ F9를 알기 전까지는 하나하나 Debug.Log() 이걸 걸고 있었습니다

그렇게 구문을 하나하나 브레이크를 걸어가면서 문제를 찾아본 결과, 스크립트에 명시된 HealthSlider 리소스와 DamageImage, DeathClip 부분이 없었기 때문에 함수 호출이 안 된다는 것을 확인했습니다. 쉽게 말하면 HP바와 피격 당했을 때 화면이 까맣게 변하는 이펙트, 죽을 때 나오는 비명 소리를 설정을 안 해뒀는데 이 리소스를 쓰겠다고 스크립트에다가 버젓이 적어놨던 것이죠. 그래서 엔진에서 "못 찾겠다 오버"라고 한 것입니다.



▲ 여기에 해당되는 리소스를 안 넣었기 때문에 오류가 발생했던 것이죠.

이 부분은 if 구문으로 막은 뒤에는 OnTriggerEnter2D와 OnTriggerExit(2D)가 문제였다는 것도 지적받았습니다. IsTrigger에 대해서 제가 기억하고 있는 것은 이거 누르면 물체가 땅에서 떨어진다는 정도였죠. 정확히는 해당 조건이 발동할 때에만 충돌이 일어나도록 하고, 그 외에 충돌은 무시하는 부분이었습니다.



▲ IsTrigger를 걸게 되면



▲ 해당 조건 외에는 충돌 및 접촉이 인식되지 않아서 떨어지게 됩니다

오브젝트에 연결된 트리거 안에 다른 오브젝트가 들어갔을 때 호출이 되는 것이 OnTriggerEnter2D인데, 이렇게 설정하게 되면 트리거를 연결한 오브젝트, 즉 적에다가 IsTrigger를 찍어야 했습니다. 그렇게 되면 자연히 적은 바닥의 Rigidbody2D나 Collider를 무시하기 때문에 추락해버리게 되죠. 결국 그 상황에서는 Collision, 즉 오브젝트의 콜라이더가 다른 콜라이더에 충돌했을 때 호출되도록 하는 형식으로 바꿔야했습니다.

이 부분은 원래 프로그래밍과 엔진 적용 부분에서 자세히 다룰 부분이지만, 간단하게 설명하자면 Rigidbody는 해당 물체가 물리 제어로 동작할 수 있도록 해주는 것입니다. 일반적인 스프라이트, 혹은 3D 물체는 게임 엔진 내에서는 질량이 없는 단순한 이미지 정도로밖에 인식을 안 합니다. 여기에 Rigidbody를 걸게 되면 그때부터 Mass, 곧 질량이 생기게 됩니다. 그렇게 되면서 개발자가 상정하는 물리적인 효과, 예를 들어 중력 같은 것이 적용이 되죠. 한 층 더 나아가 물체 간의 충돌을 구현하기 위해서는 Collider를 추가로 설정해야 합니다. Collider의 모양에 따라 Box Collider, Circle Collider, Capsule Collider 등으로 나뉘며, 2D 오브젝트를 위한 Collider의 경우 뒤에 따로 2D가 붙습니다.

앞서 언급한 문제를 해결한 뒤로는 점프 애니메이션, 점프 공격 애니메이션을 추가하면서 스크립트에 조건을 따로 붙이고, 이를 디버그 테스트하면서 계속 수정하고 있는 중입니다.



▲ 다키스트 던전 에셋은 테스트용으로만 사용하고, 실제 버전에서는 제 에셋을 사용할 예정입니다



■ 게임 안에 캐릭터만 있나요? - UI, 리소스에 대해 좀 더 생각해야 했다

"타일맵은 아시죠?"

오지현 에반젤리스트의 이 질문은 사실 조금 막막한 부분이 있었습니다. 일단 개념은 어느 정도 알고 있긴 했는데, 사실대로 말하면 사용하는 방법은 정확히 몰랐습니다. 단순히 타일맵을 지정해서 맵 위에 그리면 된다, 라는 식으로 기억하고 있었거든요. 알만툴이나 혹은 유즈맵 같은 곳에서 사용하는 것처럼, 그리드 위에다가 그냥 해당 세팅을 클릭하면 알아서 플랫폼이 만들어지는 그런 것이라고 생각하고 있었으니까요.



▲ 알만툴에서 타일맵을 깔고 맵을 만드는 것처럼 말이죠

물론 그런 형태인 건 맞지만, 그렇기 때문에 타일맵에 사용되는 Collider는 조금 다릅니다. Tilemap Collider2D가 있는데 여기에 Composite Collider 2D까지 같이 해야 타일맵을 깔 때마다 Collider가 자동으로 생성되는 방식이었죠. 현재 타일맵은 원하는 것을 아직 구하지 못했기 때문에, 임시방편으로 구한 킷에서 타일맵을 추출해서 테스트용으로 사용 중에 있습니다.

또 플랫폼을 만들기 위해서는 또 다른 것도 생각을 해뒀어야 합니다. 플랫포머라는 장르는 말 그대로 플랫폼, 즉 캐릭터가 밟아가야 하는 지형이 굉장히 중요한 게임이거든요. 그에 맞게 플랫포머에는 다양한 플랫폼이 존재합니다. 그냥 아무 것도 없이 지나갈 수 있는 평탄한 곳부터 해서 함정이 있거나 갑자기 사라지고 꺼지는 땅, 움직이는 발판, 점프해서 내리찍으면 뚫리는 지형 등 당장 기억나는 것만 해도 종류가 여러 가지였죠.

이를 어떤 식으로 분류할 것이며, 어떤 조건에 따라서 변화가 일어날 것인지 미리 생각해두는 것도 필요했습니다. 그래야 나중에 코딩을 할 때, 그에 맞는 소스 코드를 쉽게 얻을 수 있기 때문입니다. 코딩을 할 줄 안다고 가정하면, 이 부분을 미리 생각했을 때 좀 더 소스 코드를 쉽게 만들 수 있습니다. 이 과정이 소스 코드에 들어가게 될 조건문과 함수를 생각할 때 필요하거든요.

백그라운드 이미지를 어떻게 구성할 것인가, 씬을 어떻게 짤 것인가도 플랫포머에서 필요한 부분입니다. 마리오나 록맨 같은 게임을 떠올려보면, 한 스테이지에서 씬의 전환이 몇 번 일어납니다. 예를 들어 파이프를 타고 가던가, 문을 열고 들어가던가, 혹은 사다리를 타고 위아래로 갔을 때 잠시 암전이나 로딩창이 뜨면서 다른 장소로 이동하게 되죠. 이를 엔진에서는 씬의 전환으로 표현합니다. 스테이지의 어느 지점에서 어떤 오브젝트를 통해서, 어떤 조건을 활용해서 씬의 전환이 일어나도록 할 것이냐? 이런 것도 사전에 어느 정도 생각을 해둬야 나중에 배경 오브젝트를 설치하고, 코드를 짤 때 한결 더 편해지는 것이죠.



▲ 씬과 씬을 전환을 자연스럽게 해줄 오브젝트의 존재도 필요했습니다

사실 리소스, UI 등에 대해서 좀 더 생각을 해봤어야 한다고 느꼈던 건 앞서 말했던 오류 때문이었습니다. 제가 따온 코드에서는 HealthSlider라고 명명한 HP바나, 피격당했을 때 화면에 암전이 일게 하는 DamageImage, 죽었을 때 나는 소리인 DeathClip은 저도 나중에 필요로 하는 부분이었습니다. 다만 이전에는 이 부분에 대해서 그때그때 하면 되지, 라고 생각했었습니다. 물론 지금은 조금 달라졌습니다. 미리 이 부분을 먼저 캐치하고, 사전에 어느 정도 구비를 해둬야 좀 더 쉽게 체크가 가능했다는 걸 알았기 때문이죠.

사운드를 예로 들자면, 필요로 하는 BGM과 효과음의 수와 그 종류를 리스트업해두는 작업 등이 필요하죠. 그래야 나중에 오디오클립이나 오디오소스를 지정하는 작업과, 이를 불러오는 코드를 짤 때 좀 더 체계적으로 할 수 있습니다. UI 역시도 마찬가지죠. 화면에 어떤 아이콘들이 어디에 배치되어야 하고, 버튼인지 슬라이드 형식인지, 혹은 캔버스로 만들 것인지에 따라서 필요로 하는 코드도 달라지기 때문에 어떤 형식으로 갖출 것인가 생각해둘 필요가 있습니다. 예시로 작업한 HealthSlider의 경우는 슬라이더로 작업했고, DamageImage는 캔버스, 즉 화면 전체에 명도나 채도, 색상의 변화나 이미지가 뜨도록 했습니다. 버튼은 해당 이미지를 누르면 특정 화면이 뜨거나, 혹은 씬이 넘어가도록 하는 UI 오브젝트죠.



▲ 임시방편으로 UI를 만들어놓긴 했습니다

사실 이런 소소한 부분은 기획에 익숙하지 않으면 놓치기 쉬운 부분입니다. 사실 개인 차가 있는 부분이긴 하지만, 일반적으로 게임을 기억할 때 BGM, 액션, 캐릭터, 배경 등 큼직큼직한 것은 기억이 나도 효과음, 자잘한 UI 등은 크게 기억하지는 못하죠. 어떻게 보면 당연하다고 생각하기 때문에 크게 인지를 못하거든요. 그렇지만 게임을 만들어갈 때는, 그런 사소하고도 당연하다고 생각하는 부분도 만들어나가야 합니다. 이 부분을 제가 알고는 있었지만, 크게 신경을 쓰지 못했던 것이죠.



■ 이전의 기획 단계에서 무엇을 보충해야 할까?

이전의 기획 요약본을 잠시 살펴보겠습니다.

타이틀명: 제 13차원

장르: 2D 횡스크롤 액션(플랫포머에 가까운)

배경: 가상의 현대, 대한민국의 도시(경기도권, 혹은 서울)

등장 인물: 유채림(주인공), 성유미, 오중구(조력자 NPC), '뫼비우스'(악당들)

스토리 라인: 뫼비우스의 음모로 세계가 이계와 뒤엉키고 붕괴되는 상황이 발생한다. 이에 '가면'으로 자기 자신을 유지할 수 있는 일부 인원(유채림, 성유미, 오중구 등)이 '뫼비우스'에 맞서 세계를 원상복구하고자 한다.

주요 소재: '가면'

가면의 역할: 보호기재이자, 능력을 각성했다는 증거.

게임 속에서 풀어내는 가면의 역할: HP

어떻게 타 게임과 차별화를 둘 것인가?

1) 가면은 적에게 공격받거나, 함정에 걸리는 것 외에도 일정 시간이 지나면 이계의 침식 때문에 사라지게 된다. 즉 게임 오버가 된다.

2) 가면을 원상복구하는 방법은 아이템, 혹은 안전지역에서 휴식하면 된다.

사용 엔진: 유니티(겉핥기로나마 배운 적이 있어서 선택)

플랫폼: 모바일, 특히 안드로이드(iOS 구동 테스트해본 적이 없음)

사용 프로그램: 포토샵, 클립스튜디오, 그 외 유니티 에셋스토어의 에셋 등

주로 활용하게 될 에셋: 배경, 사운드 관련 에셋

큰 그림은 잡아둔 상태지만, 결국 디테일한 부분에 대해 체계적으로 명시가 안 되어있기 때문에 이와 같은 문제가 발생했습니다. 그럼 이젠 그 부분을 어떤 식으로 설정해야 할까, 하는 고민이 생기게 되죠.

사실 이 디테일을 전부 문서화한다고 하면, 기사에 다 담아낼 수 없습니다. 당장에 제가 얼기설기 만든 기획용 슬라이드나 워드 파일도 기사에 다 담기에는 양이 많은 편이거든요. 그렇기 때문에 제가 기획한 부분에서 어떤 부분이 더 채워져야 하는지만 복기하는 형태로 살펴보겠습니다.

배경의 경우는 일단 스테이지를 더 세분화해서 나눴습니다. 단순히 도시, 라고 하면 너무 큰 범위이기 때문에 학원가, 아파트 단지, 번화가 이렇게 구역을 나눴죠. 그런 뒤에는 각 파트를 세부적으로 파고 들었습니다. 예를 들어 학원가에는 어떤 건물이 있으며, 어떤 상황인지 설정했습니다. 예를 들어 학원가에는 학원들뿐만 아니라 학생들을 상대로 하는 식당이 있고, 작은 병원 같은 곳도 있죠. 건물들 대부분이 지하까지 사용하기 때문에, 지하를 테마로 하는 스테이지를 구현하기도 쉽습니다. 그리고 이런 식으로 생각을 해두면, 필요로 하는 타일맵이나 백그라운드의 형태도 조금 더 명확히 하기가 쉽죠.




사운드는 어떤 사운드를 필요로 하는지 리스트업해두는 것이 필요합니다. 크게 BGM, 효과음, 음성으로 나뉘는 데 여기서 더 나아가서 BGM은 어떤 테마에 어떤 장르 위주로 편성하며, 각 캐릭터마다 효과음이 필요한 상황이 어떤 것인지 생각해두는 것이죠. 예를 들자면 캐릭터가 공격당하거나 공격할 때, 점프할 때, 사망할 때 대다수의 게임에서는 특정한 사운드가 출력됩니다. 이러한 과정을 역으로 추적해나가면서 자신의 게임엔 어떤 효과음이 필요하겠구나, 하는 것을 도출해내는 것이죠.

앞서 기획에서는 가면에 대해서만 언급했지만, 사실 또 다른 특징인 '대검'과 이를 활용한 액션에 대해서도 기술했었어야 합니다. 사실 이 부분은 스토리보드 상으로는 대충 얼개를 짜뒀지만, 각 동작 하나하나뿐만 아니라 다른 동작과의 연결관계까지도 생각을 했어야 하죠. 사실 이 부분은 프로그래밍 파트와도 밀접한 연관이 있습니다. 각 애니메이션 간의 연결고리를 설정하는 것은 결국 애니메이터를 호출하고, 특정 파라미터를 작동하는 코드를 만들어내야 하는 것이니까요.



▲ 애니메이션을 위해서는 parameter와 Transition에 대해 염두해둬야 합니다.

그 부분까지는 가지 않더라도, 어떤 동작을 취한 다음에 다른 동작으로 이어질 때 어떤 조건이 필요한지 미리 생각해두면 앞서 말한 것처럼 좀 더 편하게 작업할 수 있습니다. 아울러 필요로 하는 애니메이션의 종류에 대해서 한 번 더 체크할 필요가 있죠. 제 경우는 게임업계 관계자로부터 "점프 공격이나 이동 공격도 구현하면 좋을 것 같아요."라고 말을 들었을 때 그 부분도 필요하다는 것을 새삼 뒤늦게 깨달았거든요.

UI는 일부 얼개를 작성해두긴 했지만, UI에 들어가는 각 아이콘의 성질이나, 혹은 그 아이콘을 눌렀을 때 어떤 일이 벌어지는지 좀 더 명확하게 작성해둘 필요가 있습니다. 예를 들자면 HP는 슬라이더 형태로 구현한다거나, 데미지가 들어갈 때 캔버스로 표현해서 화면 전체가 색상, 명도, 채도의 변화가 일어난다던가 하는 식이죠. UI의 경우 엔진에서 제공하는 UI용 슬라이더나 캔버스, 버튼 이미지 등으로 기본적인 형태는 스프라이트 없이도 미리 구현할 수 있는 만큼, 이 부분을 참고해서 UI를 정리해나가는 과정을 해두는 것도 좋습니다.

그 외에 또 한 가지, 등장하는 오브젝트에 대한 카테고리 분류도 어떻게 할 것인지 어느 정도 틀을 잡아가는 것도 중요합니다. 예를 들면 배경에서는 플레이어의 공격에 부서지는 오브젝트, 플레이어가 발을 디디면 없어지거나 떨어지는 오브젝트, 밟으면 함정이 발동하는 오브젝트 등으로 분류를 할 수 있겠죠. '제 13차원'에서는 안전지역에 대한 것도 오브젝트 분류에 반영해야 하죠.



▲ 일단 생각나는 데로 목록을 만들어두었습니다.

사실 기획 단계에서는, 생각하면 생각할수록 미리 산정해둬야 할 부분이 계속 드러나게 됩니다. 그래서 앞서서 "기획은 큰 틀로 잡고 실행에 옮기겠습니다"라고 겁없이, 그리고 무모하게 말했던 것이죠. 결국 생각만 하고 행동에 옮기지 않으면, 결과물이 남지 않으니까요. 그 댓가를 지금 톡톡히 치르면서 "좀 더 기획을 꼼꼼히 잘 할 걸"이라는 회한이 들고 있긴 합니다. 그래도 실행한 것 자체는 사실 후회는 없습니다. 작업을 계속 하면서 이게 흑역사로 남을 것 같다는 생각이 점점 강하게 들고 있긴 합니다. 그래도 다음 번에는 더 잘할 수 있을 거 같다는 생각이 조금씩 들고 있고, 이번에 겪은 실수를 반복하지 않기 위해서 이런 식으로 복기를 해나가는 것이죠.

다음 번에는 앞서 말했던 배경 및 타일맵에 대한 이야기를 이어나가고자 합니다. 에셋스토어에 대한 이야기도 나오겠지만, 포토샵으로 배경 및 타일맵을 제작하는 분투기도 아마 적게 될 것 같습니다. 지금까지 찾은 타일맵들이나 배경이 제 마음에 온전히 들지 않거든요.

결국에 타협을 하게 될지, 아니면 안 그래도 잘 못 그린 캐릭터보다 훨씬 더 엉성하겠지만 배경과 타일맵을 자급자족하게 될지는 다음에 말씀드리도록 하겠습니다.


※그래서 요약하자면?

1) 캐릭터 제작밖에 못하고, 그마저도 엉성한 상황이기 때문에 다양한 문제는 예견되어있었다. 그래서 에반젤리스트에게 솔루션을 상담하러 갔다.

2) 2D 스프라이트 애니메이션을 구현할 때, 단순히 스프라이트를 재배치하는 것이 아니라 3D에서 사용하는 것처럼 본을 삽입해서 애니메이션을 만드는 툴인 아니마 2D 툴에 대해서 알게 됐다. 스프라이트 메시는 Hierarchy창에 스프라이트를 놓고, 해당 스프라이트를 우클릭한 뒤에 Sprite Mesh를 선택하면 된다. 그리고 Sprite Mesh Editor에서 본에 Bind하면, 본의 움직임에 맞춰서 해당 이미지가 움직이게 된다.

3) 유니티 내에서 애니메이션을 만드는 방법은 Window창에서 Animation창을 활성화시킨 뒤, 애니메이션 클립을 만들고 녹화 버튼을 눌러서 각 프레임마다 자신이 원하는 동작이나, 사물의 움직임을 하나하나 구현해나간다. 각 애니메이션 동작 간의 연결은 Animator창에서 하게 되며, 각각의 상태를 Transition이라는 연결고리로 이으면 된다. Transition이 발생하는 조건은 코딩을 통해 만들어가야 하며, parameter창에서 해당 조건을 입력한 뒤에 Transition에 그 조건을 기입하면 된다.

4) 에셋스토어에 올라온 것은 상업적인 사용도 가능하다. 게임을 처음 만들거나, 프로그래밍에 익숙하지 않은 사람들을 위한 툴킷도 다양하게 존재한다. 다만 툴킷은 다른 사람이 만들어둔 틀 안에서 모든 것이 이루어지기 때문에 그 틀에 대한 것을 따로 알아야 한다. 그 외 오픈소스를 공유하는 사이트들이 있는데 사용하기 전에 라이센스 등의 문제를 미리 확인하는 것이 좋다.

5) 코드를 작성하거나 혹은 짜집기 할 때 디버깅은 필수다. 디버깅은 Debug.Log()로 체크할 수 있지만, F9로 브레이크를 걸어서 확인할 수 있다. 함수를 호출할 때, 누락된 부분이 있으면 엔진 내에서는 오류 메시지를 띄운다.

6) Rigidbody, Collision, Trigger 등 많이 사용하게 용어들은 알아두면 좋다. Rigidbody는 해당 오브젝트에 질량과 강체를 부여, 물리 효과를 받을 수 있게 한다. 이게 걸려있지 않은 물체는 엔진에서는 질량이 없는 단순 이미지 정도로밖에 인식을 하지 못한다. Collision과 Collider는 충돌에 관련된 요소이며, Trigger는 어떤 이벤트, 혹은 상태가 발생하게 하는 조건이다.

7) UI, 리소스에 대해서는 미리 생각할 필요가 있다. 게임에 쓰일 리소스가 어떤 것들이 있는지, 그리고 그 리소스는 어떤 식으로 구분해야 하는지 사전에 어느 정도 작업해두면 나중에 코드를 짜거나, 배치를 할 때 편하다. UI도 화면상에 어떤 버튼이 어떤 기능을 하며, 어떤 아이콘이 어떤 조건에 의해서 상태가 변하는지 미리 상정해두면 차후에 일괄적으로 작업하기 편하다.

8) 사운드는 필요한 BGM과 효과음의 수, 종류를 미리 리스트업해주면 나중에 오디오클립이나 오디오소스 지정하고 불러오는 코드를 짤 때 편하다. 기획에서 이런 사소한 부분을 놓치기 쉽다. 게임을 해왔을 때, 당연하다고 생각해서 별로 인식을 안 한 부분들이기 때문이다. 게임 개발할 때는 그 당연하다고 생각하는 부분도 결국 자신이 구현해야 한다.

9) 결국 최초의 기획안은 어느 정도 수정을 거쳐야 했다. 원래 처음부터 꼼꼼하게 작업했어야 하지만, 기획만 하다가 실행에 옮기지 않으면 어떤 결과도 남지 않기 때문에 이는 감수했던 부분이다. 그러나 다음 번 기획은 좀 더 나아지게끔, 기획안 수정에 대해서 언급했다.


■ 부록 - 유니티로 게임 개발하는 사람들을 위한 팁, 자습서와 인디 클리닉

유니티에는 개발자들이 엔진을 활용할 때 참고할 수 있도록 자습서매뉴얼이 존재한다. 자습서에 있는 영상 대부분은 영어라는 단점이 있지만, 강사가 언제 어떤 말을 했는지 트랜스 스크립트에 따로 기록이 되어있다. 샘플스크립트가 있는 강좌인 경우에는 샘플스크립트도 제공된다. 매뉴얼은 지속적으로 한국어화가 진행되고 있지만, 영어로 설명이 되어있는 부분이 아직도 꽤 많은 편이다.

유니티에서는 라이브 세션 외에도 인디 개발자들을 위한 '유니티 인디 클리닉'도 진행한다. 매달 두 팀을 선정, 유니티 코리아 본사에서 테크팀과 함께 개발 중인 프로젝트를 살펴보고 솔루션을 제공받는 프로그램이다(관련 기사). 그 외에도 유나이트 등 행사 현장에서 테크팀이 라이브 세션을 진행하거나, 직접 면담하고 솔루션을 제공하기도 한다.



▲ "오브젝트가 플레이어를 인식 못하는 거 같은데 어떡해야 하죠?"



▲ 일단 스크립트를 확인하고



▲ 디버깅으로 하나하나 찾아가는 작업을 거칩니다



▲ 애니메이터에 있는 파라미터와 Transition의 조건도 한 번 살펴봅니다



▲ 에셋스토어의 활용에 대한 조언과



▲ 다른 컴퓨터에서도 작업을 이어갈 수 있는 Collab 기능에 대한 설명도 들었습니다



▲ 게임 개발하시는 분들 모두 화이팅!

댓글

새로고침
새로고침

기사 목록

6 7 8 9 10