비전공자도 만드는 Unity 리듬게임 강좌의 맛보기 강의입니다.
안녕하세요. 이번 Unity 심화 강의의 첫 번째 강의 시간입니다. 강의 주제는 디펜스 게임 최적화와 그리고 리듬 게임 제작을 통해 배우는 Unity 심화 강의입니다. 우리는 이 심화 과정 강의를 통해서 Unity를 보다 효과적으로 다룰 수 있게 해주는 다양한 기법들에 대해서 공부하게 될 것입니다. 그 과정으로 Unity c#의 다양한 문법을 활용해 특정한 Unity 프로젝트를 최적화해 보게 될 것입니다. 또한 이후에는 더 심화적인 문법이라고 할 수 있는 싱글톤 기법, 오브젝트 풀링 등의 다양한 기법에 대해서 공부하게 될 거예요. 전체 강의 진행 과정은 다음과 같습니다. 먼저 기존에 존재하는 게임인 Mobile Defense Game을 분석해 보고 이를 대상으로 직접 최적화를 해보는 시간을 가져보게 될 것이고요. 또한 그러한 과정에서 Unity의 심화 개념을 몸소 익히게 될 것입니다. 그리고 최종적으로 학습한 내용과 추가적으로 공부한 내용을 바탕으로 최종 리듬 게임을 개발하게 될 거예요. 따라서 우리가 가장 먼저 해볼 것은 클래스 배열 등의 개념을 적극적으로 활용해서 특정한 Unity 게임을 최적화하는 것입니다. 여기에서 최적화란 기존 프로젝트에서 특정한 작업을 기존보다 더 전략적으로 혹은 자원을 덜 사용하도록 개선하는 과정을 의미해요. 이때 자원이라는 것은 꼭 CPU와 같은 컴퓨터 자본만을 의미하는 건 아니에요. 프로그래머의 노력, 인건비 등도 자원이기 때문에 코딩을 보다 빠르게 해주거나 프로젝트를 효과적으로 관리해줄 수 있는 도구를 적용하는 등의 작업 또한 최적화의 일환으로 볼 수 있답니다. 따라서 이 강의는 심화 과정의 강의이므로 Unity에서 c# 프로그래밍을 통한 함수 작성, Unity에서 오브젝트를 만들고 그 오브젝트의 위치 값을 변경하는 등 가장 기본적인 형태의 Unity 개발 지식이 있는 사람이라고 가정하고 강의를 진행합니다. 당연히 어떤 프로젝트가 있으면 그 프로젝트의 전반적인 내용 정도는 그래도 파악할 수 있어야, 즉 특정한 소스 코드를 보고 문제점을 진단할 수 있는 기본적인 능력이 있어야 최적화가 가능하기 때문입니다. 물론 이 강의를 들으시는 여러분은 기초 프로그래밍 지식이 그렇게 탄탄하지 않더라도 제가 강의에서 다룰 내용에 대해서는 기본적으로 빠짐없이 전부 다 화면으로 직접 보여드리면서 기존 게임에 대한 분석과 최적화를 진행할 예정이니까 너무 겁먹지 마시고 저만 잘 따라오시면 될 겁니다. 그래서 결과적으로 우리가 최적화를 하려고 하는 그 대상 게임이 어떤 것이냐 하면 말씀드렸듯이 바로 이 Mobile Defense Game입니다. 이 게임은 사실 Unity 심화 강의 이전에 Unity 기초 강의에서 최종 결과물로 만들게 되는 게임이에요. 따라서 여러분도 일단 강의 자료로 첨부를 해드린 이 프로젝트 파일을 확인해 주세요. 이 프로젝트 파일을 자신이 원하는 위치에 압축을 풀어주면 되는데요. 가급적 압축을 푸는 경로에 한글이 들어가지 않도록 해주세요. 저는 바로 이렇게 현재 폴더에서 일단 압축을 풀어줄 거고요. 압축을 풀 때 사용하는 도구로는 알집이든 반디집이든 혹은 자신의 운영체제에서 지원하는 가장 기본적인 형태의 압축 풀기 도구이든 무엇이든 상관없으니까 그냥 이렇게 압축을 풀어주면 됩니다. 저는 압축을 푼 뒤에 이 폴더의 이름을 Mobile Defense Game이라고 오직 영어만 들어가는 형태로 변경을 해주었습니다. 이것을 저는 이렇게 C 드라이브에 Unity Advanced Tutorial이라는 폴더를 만들어서 그 안에 넣어줄 수 있도록 하겠습니다. 바로 이 폴더에 이렇게 압축을 풀어 준 것과 동일한 것이고요. Unity 개발 환경을 실행해서 이 프로젝트를 열어주도록 하겠습니다. Unity 심화 강의에서는 기본적으로 Unity 개발 환경을 설치했다고 가정하고 Unity의 정말 기본적인 사용 방법 정도는 알고 있다고 가정하고 진행하기 때문에 Unity의 설치 과정에 대해서는 현재 강의에서 다루지 않을 예정입니다. 최신 Unity 개발 환경에서는 이와 같이 Unity Hub를 이용해서 다양한 Unity 개발 환경을 직접 설치하고 버전별로 관리할 수 있도록 해줍니다. 저는 제가 강의를 촬영하는 시기에 가장 최신 버전인 Unity 2018.3.5 버전을 사용해주도록 하겠습니다. 저는 곧바로 이것을 다운로드해 줄 것이고요. 우리가 나중에 만들게 될 2D 리듬 게임은 Android 스마트폰에서도 돌아갈 수 있는 게임이기 때문에 이와 같이 Android Build Support 또한 선택해서 설치를 진행해 주시면 됩니다. 또한 이렇게 아래쪽에는 Documentation도 존재하는데요. 이것 또한 설치하시면 좋습니다. 결과적으로 기본적인 옵션에서 Android가 잘 선택이 되어 있는지 확인해 주시고 이렇게 설치를 진행해 주시면 됩니다. 본 강의는 2018년 이후에 출시가 된 Unity 개발 환경이라면 어떤 것을 선택을 하든지 간에 호환성에 있어서 어려움 없이 따라올 수 있게 될 것인데요. 저는 그래도 이왕이면 현재 강의를 촬영하는 입장에서 가장 최신 버전의 Unity를 설치해서 그것으로 진행을 하고자 합니다. 저는 결과적으로 이와 같이 Unity 2018. 3. 5 버전을 설치 완료했고요. 만약에 여러분 화면에 이것과 완전히 동일한 Unity 버전이 없다고 하더라도 그냥 단순히 2018년 이후 버전으로만 설치를 진행해서 따라와 주시면 감사하겠습니다. 이렇게 설치된 이후에는 On my machine 탭에서 현재 우리 컴퓨터에 설치가 되어 있는 Unity 개발 환경의 버전을 확인할 수 있고요. Open 버튼을 눌러서 방금 전에 우리가 다운로드를 받고 압축을 풀어줬던 이 Mobile Defense Game을 열어주도록 하겠습니다. 확인하시면 크기가 작지 않아요. 약 200MB에 가까울 정도로 작지 않은 크기인데 이것을 한번 열어보도록 하겠습니다. 바로 Open 버튼을 눌러주시고요. 이렇게 Mobile Defense Game을 눌러서 열어주도록 하겠습니다. 그러면 이와 같이 Unity로 개발된 다른 프로젝트를 열 때 어떤 Unity 버전으로 열지 물어보는 것을 확인할 수 있는데요. 저는 이와 같이 방금 전에 설치한 Unity 버전으로 Open을 해주겠습니다. 다만 이 Mobile Defense Game은 제가 Unity 기초 강의에서 다루었던 내용으로서 당시에는 2018년도 2.3 버전이 최신 버전이어서 이것을 이용해서 개발을 진행했었는데요. 심화 과정을 찍는 지금 시점에서는 2018년도 3.5버전이 최신 버전이니까 이것으로 열어주도록 하겠습니다. 기본적으로 Unity에서는 그 이전 버전에서 만들었던 프로젝트도 상위 버전에서 열었을 때 최대한 문제가 없도록 호환성 관리를 잘해주고 있기 때문에 이런 메시지가 뜰 때는 Upgrade 버튼을 눌러서 프로젝트를 열어 주시면 됩니다. 참고로 처음 프로젝트를 열 때는 다소 시간이 소요될 수 있으니까 넉넉히 기다려 주세요. 프로젝트가 열리면 하나의 Mobile Defense Game이 등장하게 될 것입니다. 이번 시간에 하고자 하는 궁극적인 것은 바로 이 Mobile Defense Game의 전반적인 사항을 훑어보는 것입니다. 따라서 가장 먼저 이 Game View로 이동해서 화면의 해상도를 바꾸도록 하겠습니다. 화면의 해상도에서 아래쪽에 + 버튼을 눌러서 해상도를 1920 × 1200으로 설정하겠습니다. 이전 기초 강의에서 Mobile Defense Game 개발을 진행할 때 이와 같이 모바일상에서 1920 × 1200의 해상도를 가지는 형태로 게임을 개발했기 때문에 이렇게 고정 해상도를 사용하기 때문에 이와 같이 Game View에서 1920 × 1200으로 설정한 것이고요. 지금부터 이 Mobile Defense Game의 기본적인 내용을 훑어볼 것인데요. 한 가지 명심하면 좋은 게 있는데요. 지금 모든 내용을 깊게 다 이해할 필요가 없어요. 저와 같이 여러 강의에 걸쳐서 이 프로젝트를 계속 살펴보시면 Unity 기초 강의를 듣지 않은 분들도 이 프로젝트의 전반적인 내용을 쉽게 이해할 수 있게 될 겁니다. 또한 Unity 기초 강의를 진행하면서 Mobile Defense Game을 만들었을 때 저는 학생분에게 클래스의 개념도 가르치지 않았습니다. 오직 정말 기본적인 프로그래밍 지식만 가지고 이러한 Mobile Defense Game을 만들어 봤던 것이고요. 우리는 심화 강의이므로 고급 프로그래머의 입장에서 이런 Mobile Defense Game을 분석하고 소스 코드를 확인해서 최적화를 해보는 시간을 가지게 되는 것입니다. 그러니까 기본적으로 모바일 디펜스의 전체 소스 코드와 전체 오브젝트를 다 이해하려고 하지 마시고요. 제가 강의에서 다루는 내용만 이해하셔도 향후 리듬 게임 개발 강의까지 따라올 수 있을 것이니까요. 만약에 이해가 잘 안 가는 부분이 있다고 하더라도 강의에서 다루지 않은 부분은 크게 신경을 쓰지 않고 강의를 쭉쭉 듣는 것을 추천드립니다. 가장 먼저 Project View로 이동해서 모든 리소스가 포함되어 있는 이 Assets 폴더를 확인해 보도록 하겠습니다. Unity에서는 Assets 폴더가 가장 기본적인 폴더로 잡혀 있는데요. 일반적으로 여기에 Animation, 프로그램 Script 등이 전부 다 들어가게 됩니다. 가장 먼저 확인해 볼 것은 바로 Scenes 폴더인데요. Scenes 폴더에서는 게임 내에 사용되는 모든 Scene이 담기는 공간입니다. 보면 GameScene과 StartScene이 존재하는 것을 확인할 수 있는데요. 현재 눈에 보이는 Scene은 바로 StartScene입니다. 즉 현재 눈에 보이는 화면은 게임의 시작 화면인 StartScene에 해당하는 것이고요. 실제로 사용자가 보게 되는 화면은 이 Game View의 이러한 화면이고요. 실제로 게임을 간단하게 실행해서 테스트를 진행해 보시면 이와 같이 게임 시작과 게임 종료에 마우스를 갖다 대면 약간 색상이 변경되면서 버튼인 것처럼 동작하는 것을 확인할 수 있습니다. 여기에서 게임 시작 버튼을 누르면 실제로 Mobile Defense Game이 시작되는 것이고요. 다시 이렇게 실행 종료시켜 줄게요. 실제로 게임 시작이 이루어지도록 해주는 로직은 바로 Scrpits 폴더의 StartManager Script에 그 내용이 정리되어 있습니다. 이것을 더블 클릭해서 열어보도록 할게요. 이렇게 Script를 열어보시면 이와 같이 소스 코드를 확인할 수 있습니다. 가장 먼저 GameStart라는 함수가 눈에 보이실 건데요. 바로 사용자가 게임 시작 버튼을 누르면 이 함수가 실행되는 것입니다. 보면 GameScene이라는 다른 Scene이 열리도록 코딩되어 있네요. 또한 아래쪽에는 Start 함수 안에서 처음 게임이 실행되면 해상도를 1920 × 1200으로 고정시키는 것을 확인할 수 있고요. 또한 아래쪽에는 ShowRewardedAd라고 해서 Unity 광고 관련 함수가 작성되어 있습니다. 간단히만 언급 드리면 실제로 게임 시작 버튼을 눌러서 Mobile Defense Game을 실행하게 되면 가장 먼저 Unity 광고부터 보여줘서 사용자가 광고를 봄으로써 이제 게임 개발자 입장에서 수익을 창출할 수 있게 되는 구조입니다. 아래쪽에 있는 내용은 실제로 광고와 관련한 처리를 해주는 것이기 때문에 자세한 내용은 살펴보지 않도록 하겠습니다. 이렇게 게임을 실행해 보시면 기본적으로 게임 시작 버튼을 눌렀을 때 사용자에게 동영상 형태의 광고가 보이게 됩니다. 물론 광고 초기화가 늦게 돼서 처음 게임을 시작했을 때는 광고 화면이 보이지 않을 수 있어요. 아무튼 이렇게 실제로 게임을 실행해 보면 이와 같이 동영상 형태의 광고가 출력되는 것을 확인할 수 있어요. 광고 닫기 버튼을 누르면 바로 현재 게임이 실행되고 있는 것을 확인할 수 있고요. 간단히 게임을 플레이해 볼 수도 있습니다. 이와 같이 정상적으로 게임이 동작하는 것을 확인할 수 있고요. 실제로 이와 같이 게임 시작 버튼을 눌러서 GameScene으로 이동했을 때 정확히 게임 내에서 어떤 일이 벌어지는지 확인하기 위해서 Scenes 폴더에서 GameScene으로 이동해 보도록 할게요. 여기는 실제로 게임이 실행됐을 때 실질적으로 사용자가 만나게 되는 그러한 화면인데요. 기본적으로 게임이 실행되면 CreateMonster Script에 의해서 Monster가 반복적으로 오른쪽에서 출연하게 되는 것입니다. Hierarchy View에서 Respawn Spots에 적용되어 있는 것을 확인할 수 있고요. 다시 말해서 리스폰 지역이라고 해서 총 4개의 지역에서 랜덤하게 Monster가 출몰하게 되는 것입니다. 그러한 Monster 출몰과 관련한 Script 처리는 바로 이 Create Monster Script가 진행을 해주고 있는 것이고요. 실제로 이 Script에 의해서 Game Manager에서 정의해 놓은 Total Round, 즉 최종 라운드인 10라운드까지 반복적으로 매 라운드마다 Monster를 생성하도록 해줍니다. 그렇다면 이러한 Game Manager는 어떻게 정의가 돼 있을까요. Game Manager Script를 열어보도록 하겠습니다. Game Manager Script를 열어 보면 게임 전반에 관련된 다양한 변수가 선언되어 있는 것을 확인할 수 있습니다. Total Round에는 전체 라운드 수, reward는 한 라운드가 끝났을 때 얻는 보상, 즉 씨앗의 개수 그리고 spawnTime은 각 Monster가 출몰하는 시간 차이 그리고 spawnNumber는 라운드마다 출몰하는 Monster의 마릿수입니다. 아래쪽으로 내려와 보시면 decreaseLife 함수가 존재하는데요. 이 함수는 Monster가 왼쪽 끝까지 도달해서 목숨이 감소되는 함수예요. 그리고 GameClear 함수는 게임을 최종 라운드까지 전부 다 클리어했을 때 클리어 메시지를 보여주는 함수고요. select 함수는 실제로 게임을 진행할 때 우리가 Character 포탑을 설치할 수 있는데요. Character 1과 Character 2 중에서 어떤 Character를 화면에 설치할지 고르는 함수입니다. 다시 Create Monster Script를 열어보도록 할게요. 아까 전에 말씀드렸듯이 Respawn Spots에서 실제로 Monster를 생성하는 Script가 Create Monster Script라고 말씀을 드렸죠. Create Monster Script는 GameManager만큼 중요한 Script인데요. 보시면 아래쪽에서 Update 함수 내에서 반복적으로 리스폰을 수행하는 로직이 들어가 있습니다. 실제로 리스폰을 할 때마다 총 4개의 리스폰 지역에서 하나를 선택해서 리스폰이 이루어지는 것을 확인할 수 있고요. 실제로 선택된 그 리스폰 지역에서 monsterPrefab, 즉 Monster 오브젝트를 생성해서 생성된 Monster는 오른쪽에서 왼쪽으로 계속해서 출발하게 된다는 것이죠. 다만 지금 보시면 여기에서 개선을 할 필요가 있는 소스 코드가 눈에 보여요. 총 4개의 리스폰 지역 중에서 어떤 것을 선택할지 고르기 위해서 1부터 4까지 랜덤한 숫자를 하나 고른 뒤에 그 랜덤한 숫자에 맞는 Spot을 정해서 거기에서 Monster가 출몰하도록 만드는 것을 확인할 수 있는데요. 지금 보시면 1부터 4까지 전부 다 일일이 소스 코드로 이렇게 조건문을 활용해서 리스폰이 이루어질 위치를 고르는 것을 확인할 수 있어요. 어떻게 생각하시나요? 만약 리스폰 지역이 4개가 아니라 100개가 넘는다면 어떻게 될까요? 이런 식으로 하나하나씩 다 일일이 코드를 적게 되면 이러한 if문, 즉 조건문이 총 100개가 들어가게 되겠죠. 만약 리스폰 지역이 많아지더라도 이러한 방식의 소스 코드를 이용할 수 있을까요? 아마 어려울 거예요. 이렇게 다수의 동일한 오브젝트를 처리하는 방법으로는 바로 배열이 있는데요. 향후 우리는 배열을 이용해서 이러한 소스 코드를 개선하게 될 것입니다. 다시 한번 게임을 실행해 볼 건데요. 우리는 아까 전에 이 Monster가 나오는, 즉 Monster가 리스폰되는 그러한 동작이 어떠한 Script에 의해서 이루어지는지 확인해봤습니다. 그렇다면 실제로 타워를 건설했을 때 이렇게 Monster가 생성돼서 Monster가 폭탄을 발사하는 이러한 역할은 어떠한 Script가 진행하고 있는지에 대해서 알아보도록 할게요. 기본적으로 각 타일을 눌렀을 때 Character가 생성되고 Character가 죽게 되면 Character 오브젝트가 다시 사라지게 되는 것을 확인할 수 있습니다. 하지만 Character 오브젝트가 직접 생성돼서 우리의 컴퓨터 메모리에 올라갔다가 Character가 죽게 되어 다시 오브젝트가 우리 컴퓨터 메모리에서 해제되는 그러한 과정이 많이 반복되게 되면 컴퓨터의 자원에 큰 부담을 줄 수 있어요. 특히 지금은 그래도 Character를 이렇게 각 타일을 눌렀을 때만 생성되고 폭탄 또한 한정적으로 발사가 되기 때문에 게임 오브젝트가 그렇게 많지 않아서 그러한 오브젝트의 생성과 삭제 때문에 발생하는 렉이 적은 편인데요. 만약에 지금보다 더 많은 게임 오브젝트가 실시간으로 생성되고 삭제가 되어야 하는 게임에서는 렉이 걸리기 쉽습니다. 특히 실제 이 게임은 컴퓨터 화면이 아니라 모바일 환경상에서 구동이 되는 그러한 겜이기 때문에 특히 렉이 걸리기 쉬워요. 결과적으로 이는 나중에 배우게 될 오브젝트 풀링 기법을 이용해서 현재의 소스 코드를 개선시키는 방법에 대해서 알아보게 될 것입니다. 다음으로 확인해 볼 것은 바로 Character Behavior Script입니다. 이것은 건설된 Character 타워의 행동을 지정해주는 거예요. 말 그대로 우리가 설치한 그 Character가 어떤 행동을 보일지에 대해서 설정한 것입니다. Script를 열어 보면 아래쪽에 Attack 함수를 통해서 하나의 총알 객체를 Instantiate 함수를 이용해서 만든 뒤에 그 총알의 공격력을 설정해서 그 총알이 실제로 발사될 수 있도록 처리한 것을 확인할 수 있습니다. 그런데 생각해 보면 Character 또한 Monster를 만나면 이렇게 총알을 발사하는데 Monster 또한 사실 Character를 만나면 공격을 수행하죠. 그렇다면 Character의 행동에 대해 정의하는 Character Behavior Script가 있으니까 Monster 행동에 대해서 정의하는 Monster Behavior Script도 존재할 것입니다. 바로 이 Script인데요. 이 Script를 열어서 Monster가 Character를 만나면 공격을 수행하는 등의 내용이 작성되어 있는 것을 확인해보도록 할게요. 아래쪽으로 내려가 보면 Unity 내에서 오브젝트의 충돌을 감지하는 OnTriggerEnter 함수 내에서 가장 왼쪽에 있는 울타리를 만나면 Monster가 제거되면서 실제로 우리 게임의 목숨값을 1 감소시키는 것을 확인할 수 있고요. 반대로 Character를 만나게 되면 공격을 수행하는 애니메이션을 보여주면서 실제로 공격을 수행할 수 있도록 Character를 타깃으로 설정하는 것을 확인할 수 있습니다. 공격을 수행하도록 개발되어 있는 거예요. 현재 충돌을 감지한, 즉 Character를 만났을 때 그 Character의 Characterstat이라는 Script를 확인해서 그 Character의 체력 값을 감소시키도록 개발되어 있는 것을 확인할 수 있는데요. 다시 말해서 Monster와 Character의 공격력, HP 등의 그러한 정보는 각각 stat이라는 이름의 Script에 명시되어 있습니다. 따라서 Character stat이라는 Script를 열어보도록 할게요. 여기가 실제로 한 명, 한 명 Character에 적용되어 있는 Character의 stat 데이터입니다. 보면 Monster를 공격할 때의 공격력인 damage 변수가 정의되어 있고 자신의 체력을 의미하는 hp와 maxHp 정보가 담겨 있는 것을 확인할 수 있습니다. 이번에는 이어서 Monster stat Script를 열어보도록 할까요. Character와 마찬가지로 damage, hp, maxHp 변수가 존재하는 것을 확인할 수 있습니다. 여기에서 동일한 변수가 존재하는 것을 보고 어떤 생각이 드시나요? 바로 공통된 속성이 존재한다는 것을 눈치챌 수 있어요. 이렇게 똑같이 hp와 damage가 Monster와 Character 둘 다에게 존재하는 것을 확인할 수 있죠. 하지만 실제로 현재 Script상에는 이렇게 Monster에서도 따로 damage와 hp를 정의해 주었고 Character 또한 따로 이렇게 hp와 damage를 정의해 준 것을 확인할 수 있어요. 불필요하게 공통된 내용을 여러 번 정의한 것을 확인할 수 있습니다. Unity에서 개발할 때는 여러 오브젝트들의 공통된 속성을 클래스와 상속의 개념을 활용해서 효과적으로 처리할 수 있으며 전체 소스 코드의 라인 수를 획기적으로 줄여줄 수 있답니다. 이번 시간에는 간단하게 Mobile Defense Game의 기본적인 구성에 대해서 살펴보는 시간을 가져봤는데요. 우리는 앞으로 이러한 게임 프로젝트를 분석하여 전문 고급 개발자가 된 것처럼 기존 프로젝트의 안 좋은 점을 하나씩 고치며 최적화를 해보는 특이한 방식으로 Unity 심화 문법을 학습하게 될 것입니다. 다음 시간에는 본격적으로 심화 문법을 학습하면서 그와 동시에 이러한 Mobile Defense Game을 개선해보는 실습을 하면서 강의를 진행하게 될 것인데요. 다음 시간에는 가장 먼저 프로젝트 관리 도구에 대해서 공부하게 될 것입니다. 이번 시간에는 이와 같이 우리가 앞으로 분석하게 될 Mobile Defense Game까지 간단히 분석해 보는 시간을 가져봤습니다.
