Unity 4.3에서 첫 2D 기능을 소개합니다.
이를 알아보기 위해 이 툴을 이용하여
데모 프로젝트를 만들어봤습니다.
이 2D 플랫폼 게임은 Tower Bridge Defence라고 합니다.
외계인의 습격을 받은 영국의 타워 브리지를
묘사하고 있습니다.
이는 스프라이트 및 물리 기반의 2D 샘플 레벨로
유니티를 통해 어떻게 2D 게임을 만들 수 있는지
보여드리고자 합니다.
이 비디오를 통해 데모에서 사용된
배경과 전경 제작, 캐릭터, 효과, 카메라 추적,
애니메이션 및 스크립팅에 대해
설명하겠습니다.
우선 유니티에서 2D를 어떻게
사용하는지 기초부터 알아보겠습니다.
2D 작업을 위해서 가장 먼저 여러 설정에서
Editor Behaviour Mode를
2D로 설정해야 합니다.
이는 프로젝트 마법사의 드롭다운 메뉴를 사용하여
새로운 프로젝트를 만들 때 설정하거나, 작업 중에
상단 메뉴에서 Edit - Project Settings - Editor를
선택하여 설정할 수 있습니다.
이렇게 하면 기본적으로 텍스처를
스프라이트로 가져오게 되고
Scene View는 2D 모드로 기본 설정됩니다.
이 설정으로 2D 게임 제작에 필요한 완전한 직교 뷰
(orthographic view)가 제공됩니다.
또한 화면의 오른쪽 상단에 일반적으로 위치한
3D 기즈모를 숨겨 더 넓은 작업 공간을 확보할 수
있습니다. 이러한 설정 이외에도 2D 워크플로우는
유니티의 기존 3D 게임 제작 방식을
그대로 반영하도록 설계되었습니다.
즉, 이미 유니티에 대해 알고 있는 사용자라면
2D 게임 제작을 바로 시작할 수 있는 유리한 위치를
선점하신 겁니다.
유니티에서는 2D와 3D를 함께 섞어 사용할 수 있다는 점에
주목할 필요가 있습니다. 예를 들어
2D 게임에 3D 요소를 추가하고 싶다면(반대의 경우도 마찬가지)
아무런 문제 없이 진행할 수 있습니다.
데모 프로젝트를 살펴보면서 어떻게 완성되는지
하나씩 살펴보도록 하죠.
우선은 샘플 레벨의 레벨 디자인을
스케치하는 것으로 시작하여
포토샵에서 레이아웃을 만드는 작업을 거칩니다.
만들어서 내보낸 레이어는
새로운 스프라이트 유형으로
유니티에 가져올 수 있습니다.
나중에 배경에 시차(parallax)를 생성하려면
배경 요소의 일부를 분리해서
Background Sorting Layer에 위치시킵니다.
유니티의 또 다른 2D 개발 기능입니다.
이 레이어에 모든 배경을 할당한 다음에는
Sprite Renderer의 Order In Layer 속성을 이용하여
정렬할 수 있습니다.
모든 위치가 지정되면
Background Sorting Layer를 잠글 수 있습니다.
이를 잠금으로써 전경 요소 추가 시
실수로 배경 요소를 드래그할지도 모른다는
걱정에서 벗어날 수 있습니다.
이는 인터페이스 오른쪽 상단의 풀다운 메뉴인
Layers에서 실시할 수 있습니다.
배경 요소는 순전히 장식용이기 때문에
스프라이트 게임 오브젝트에는
추가 요소가 필요 없습니다.
이들은 BackgroundParallax라고 불리는
시차 조절을 위한 단순한 스크립트가 포함된 빈 게임 오브젝트에
하위(child) 관계로 지정되었습니다.
이 스크립트는 Scripts 폴더에서 확인할 수 있습니다.
아주 자세한 주석과 함께 설명되어 있습니다.
이제 캐릭터들이 실제로 뛰어다닐
전경 요소를 생성할 차례입니다.
런던 타워 브리지에 가운데에 UFO가 착륙한 모습을
디자인했습니다.
캐릭터는 하늘에서 나타나는 적을 피해 배경에서
자유롭게 돌아다니면서 다음 레벨로
진행해 나갑니다.
그러므로 각각의 전경에는 캐릭터가 걸음을 디딜 수 있는
충돌체가 필요합니다.
효율성을 위해 대부분의 배경에는
2D 박스 충돌체(Box Collider)를 사용하지만
UFO는 복잡한 형태를 지니고 있습니다.
유니티의 폴리곤 충돌체(Polygon Collider)를 사용하면
스프라이트의 형태를 기반으로
충돌체가 자동으로 생성됩니다.
이는 나중에 충돌체의 형태를 변경할 수도 있음을
의미합니다.
충돌체 형태의 포인트들을 이동, 추가 또는 빼서
걸어 다니기에 더 적합하게
만들 수 있습니다.
이러한 전경을 분류하기 위해
Foregrounds Sorting Layer를 생성합니다.
이 레이어는 Tags And Layers 관리자의 배경에 앞서게 위치시킵니다.
다음으로 우리의 주인공을 살펴보죠.
플레이어 캐릭터도 포토샵에서 디자인되었는데
이 데모에서는
2D 대작 게임의 주인공인 Rayman 같은
독립적인 팔다리와 기능을 가진
캐릭터를 만들기로 했습니다.
또 다른 방법으로 스프라이트 시트 기반의
애니메이션으로 포토샵에서 개별 프레임을
디자인할 수도 있습니다.
이는 나중에 배경에 있는 백조에 사용하게 될 방법으로
본 비디오 후반에 설명하도록 하겠습니다.
여기서 캐릭터의 개별 요소를 움직이게 하려면
디자인을 완성한 뒤 신체 요소들을
캔버스의 별도 공간으로 이동시켜
유니티가 이들을 Importer에서 개별 스프라이트로
분리시키도록 합니다.
이는 모든 스트라이트를 움직이는 개별 요소들로
정할 수 있다는 뜻입니다.
이 요소들을 방금 생성한 Character Sorting Layer에
위치시키고 Transform(변환) 내 Z값을 조절해
원하는 렌더링 깊이로 정렬합니다.
이제 이 모든 스프라이트는
컨트롤 스크립팅, 충돌체, 물리 등이 모두
포함되어 있는 빈 게임 오브젝트 내에 정렬됩니다.
여기까지 완성되면 캐릭터의 각각의 스프라이트를 애니메이팅하여
Idle, Run, Jump, Shoot 및 Death 애니메이션을
만들 수 있는 업그레이드된 애니메이션 창을
사용할 수 있게 됩니다.
애니메이션 창의 새로운 도프시트 보기 덕분에
이 작업이 정말 편해졌습니다.
애니메이션을 상위(parent) 오브젝트에 추가하고
하위(child) 오브젝트의 키프레임을 생성하면 됩니다.
원하는 곳으로 플레이헤드를 옮긴 후
캐릭터의 여러 부분을 옮기면
키프레임 애니메이션이 자동으로 만들어집니다.
애니메이션을 커브와 도프시트 사이에서
전환하여 볼 수 있기 때문에 타이밍과 디자인 조절이
정말 쉬워졌습니다.
이렇게 생성된 애니메이션으로
캐릭터의 상태 머신을 디자인하면
코드가 호출되었을 때 여러 가지 애니메이션을
재생할 수 있습니다.
캐릭터의 애니메이터 컨트롤러는
3D 바이패드로 구동되는 것이 아니므로
물리 엔진에 맞춰 애니메이션을 구동하려면
Apply Root Motion의 선택을 해제하고
Animate Physics를 선택합니다.
배경에서 움직이게 하려면 주인공의 발에는
원형 충돌체를 지정하고 나머지 몸통 부분에는
박스 충돌체를 지정합니다.
이를 통해 주인공은 오르막을 자연스럽게 오르내릴 수 있고,
점프하면 천장에 머리가 닿게 됩니다.
캐릭터와 캐릭터 움직임을 제어하기 위해
2D 물리 포스 내에서 움직이도록 스크립트를 작성했습니다.
이를 통해 게임 중 물리를 주인공과 적에게
적용할 수 있어 더욱 역동적인 게임 플레이가
가능합니다.
캐릭터의 PlayerControl 스크립트에서
플레이어의 입력(input)을 확인합니다.
이를 사용하여 물리 포스를 움직임에 적용하고
입력 값을 애니메이터에게 전송함으로써
어떤 애니메이션이 재생될지 정의하고
상태(state)로 생성한
여러 가지 애니메이션 클립 간의
매끄러운 전환이 가능해집니다.
애니메이션 클립에서 상태를 생성할 수 있는
애니메이터를 사용해서 가장 좋은 점은
다시 애니메이션 작업을 하지 않아도 물리 속도에 맞게
애니메이션의 속도를
조절할 수 있다는 것입니다.
FixedUpdate 함수는 각 물리 단계를 평가한 다음
가장 먼저 하는 것은
Horizontal 입력 값을 애니메이터의
Speed 매개변수에 공급하는 것입니다.
단순한 상태 머신에서 Idle과 Run 간에
전환하려면 Speed 매개변수가
0.1 이상이어야 합니다.
그렇게 되면 애니메이터는 Idle에서 Run 상태로
블렌딩합니다.
그리고 나서 움직이도록 하려면
플레이어의 2D 물리 요소인 rigidbody2D에
포스를 추가합니다.
또한 Horizontal 입력 값이 0 보다 높은지 낮은지 확인하여
캐릭터가 어느 방향을 바라보게 만들지
결정합니다.
그 원리는 유니티 내에서 왼쪽 입력 키를 누르면
-1 값이 되고 오른쪽 입력 키는 +1 값이 되기 때문입니다.
입력에 따라 캐릭터의 X축을 역전시켜
캐릭터를 반대 방향으로 바꾸는
뒤집기 함수를 호출합니다.
플레이어가 지상에 있도록 정하려면
Ground라고 하는 유니티 레이어를 추가하고
캐릭터가 걸어 다닐 수 있는 전경 표면 전체에 적용합니다.
2D의 Linecast 함수를 사용하면
Ground 레이어에 속한 요소 중 캐릭터의 발밑에 위치한 것이 있는지
확인할 수 있습니다.
이를 더 손쉽게 커스터마이징하기 위해
지상을 확인할 수 있는 포인트로 사용할
빈 게임 오브젝트를 생성합니다.
이 빈 오브젝트에 기즈모를 추가하면
캐릭터 아래로 얼마나 먼지 조종할 수 있어
지상을 확인할 수 있습니다.
이것은 게임플레이 측면에서 보면 캐릭터가
지상에 있을 때만 점프할 수 있다는 뜻이 됩니다.
플레이어 제어에 대한 자세한 정보는 스크립트의
다른 코멘트를 확인하십시오.
플레이어의 무기는 비디오 후반에
살펴보겠습니다.
이제 데모에서 카메라가 어떻게 플레이어를
추적하는지 알아보겠습니다.
3D 게임과 마찬가지로 2D 게임에서도
액션을 추적하는 카메라의 움직임이
게임을 완성되게 만들 수도, 망칠 수도 있습니다.
전통 2D 플랫폼 게임을 만들기 위해 2D 게임 역사에서
가장 흥미로운 카메라 기법을 사용했던
슈퍼 닌텐도 또는 슈퍼 패미콤용 게임인
Super Mario World를 살펴보겠습니다.
Super Mario world에서 카메라는
수평으로 움직이지만 Viewport 중심에서
사각지대 또는 여백을 사용하므로
캐릭터가 조금씩 움직일 때는
카메라가 쫓아가지 않아도 됩니다.
캐릭터가 여백 밖으로 이동하면
그제야 카메라가 따라옵니다.
Super Mario World 카메라는 수직으로 순간 이동하기 위해
특정한 높이를 사용합니다.
앞으로 스테이지가 추가되면 필요하겠지만
현재 이 게임에서는 X축으로 긴 레벨이 없으므로
이러한 세부 사항까지는 필요 없습니다.
이러한 이유로 카메라는 수평 작동 방식과
비슷하게 수직으로 이동합니다.
mainCamera 게임 오브젝트에서 CameraFollow 스크립트의
코멘트를 통해 이러한 효과를 어떻게
만들었는지 확인해 보십시오.
이 게임에서 사용된 효과가 몇 개가 있으나
주인공이 맞닥뜨린 외계인 학살자들을 공격하여
처치하는 능력이 가장 중요합니다.
주인공은 반동으로 발사되는 바주카를 사용합니다.
이 동작은 여러 부분으로 나누어집니다.
먼저 키 입력을 정하고, Fire 키가 눌러지면
로켓의 인스턴스를 만들고
오디오 클립을 재생하여 재생할 애니메이션 상태를 작동시킵니다.
좀 더 자세하게 알아보도록 하죠.
Run과 같은 다른 애니메이션 재생 중에
Shoot 애니메이션을 재생하려면
애니메이터 내에 Shooting이라는 별도의 레이어를
만들어야 합니다.
여기서 Weight 속성을 1로 설정하면
Shooting 레이어에서 클립으로 움직이는
캐릭터의 모든 부위에 대한 움직임을 기본 레이어에서
완전히 재지정할 수 있습니다.
이 레이어에서 Shoot 트리거 매개변수가
코드에서 호출될 때 Shoot 애니메이션을
다른 상태로 전환합니다.
이 부분을 맡고 있는 Gun 스크립트를 확인해 볼까요?
애니메이터에 접근하여 트리거를 True로
설정한 것을 확인할 수 있습니다.
트리거는 스위치로 작동하며 다음 프레임에서 스스로 False로 재설정해
다시 호출할 수 있게 만들기 때문에
Shooting과 같은 동작에 최적입니다.
이 스크립트에서는 애니메이션 설정뿐만 아니라
로켓을 발사하고,
오디오 클립을 재생하고,
플레이어가 바라보는 방향에 따라
로켓의 인스턴스를 만들고 속도를 지정합니다.
이는 X축에서 양수 또는 음수로 표시됩니다.
이 스크립트는 주인공의 hierarchy의 빈 게임 오브젝트인
Gun에 포함되어 있습니다.
코드를 이런 방식으로 빈 게임 오브젝트에 놓으면
로켓이 생성될 자리를
쉽게 잡을 수 있습니다.
바주카 끝 부분에
빈 오브젝트를 위치시키고,
로켓이 나타날 지점으로
그 위치를 사용하게 됩니다.
2D rigidbody로 만들어진 로켓이
움직이게 만들려면
속도를 지정해야 합니다.
스트라이트 전환 불꽃 배기가스에
연기를 표현하는 파티클 시스템이 있습니다.
파티클 시스템은 새로운 스프라이트 그래픽 유형을 허용합니다.
그러므로 재질에 연기 스프라이트 시트를 추가하여
파티클 시스템의 텍스트 시트 애니메이션 모듈에
할당할 수 있고 파티클 배출용 스프라이트의
즉각적인 애니메이션을
확보할 수 있습니다.
로켓이 적을 강타하거나 배경의 일부에 맞으면
로켓은 파괴되고
폭파가 일어납니다.
이러한 폭파는 생성한 스프라이트 시트를 통해
애니메이팅 되는 스프라이트 게임 오브젝트입니다.
그리고 다시 분류 레이어를 사용하여
모든 전경 오브젝트 중 가장 낮은 레이어 순서에서 렌더링합니다.
이러한 스프라이트 기반 애니메이션을 추가할 때
Project 패널의 파일을 선택하고
Sprite Mode Multiple을 선택하여
스프라이트를 설정합니다.
이를 통해 Sprite Editor에 액세스할 수 있어
수동 또는 자동으로 자를 수 있습니다.
파일에서 적절한 스프라이트를 선택한 후
Apply를 클릭하면
유니티에서 프로젝트에서 사용할 파일의
하위 스프라이트를 생성합니다.
로켓 만들기 아주 간단하죠?
적을 처치하는 기법은 비디오 후반의
적군 편에서 확인하겠습니다.
플레이어 캐릭터로 돌아가서 체력과 적에게 입은
피해를 어떻게 처리할지 확인해 보겠습니다.
체력은 부동(Float)으로 저장되고
적과 닿아서 생기는 상호 작용을
TakeDamage 함수라고 부릅니다.
이는 repeatDamagePeriod가 지났을 때만
작동하여 플레이어가 너무 일찍
죽는 것을 방지합니다.
플레이어가 적을 더 쉽게 피하고
피해를 입었을 때 알 수 있도록
캐릭터가 물리적으로 피해를 받고
반동으로 튕겨 나가게 만듭니다.
이를 위해 TakeDamage 함수는 물리 포스를 추가하여
플레이어의 잠시 점프하지 못하게 만들고
적의 플레이어를 향한 벡터를 찾아
적을 해당 방향으로
튕겨 나가게 합니다.
hurtForce 변수는 Inspector에 공개되어 있어
스크립트로 다시 돌아가지 않고
게임 플레이의 해당 요소를 조정하도록
변경할 수 있습니다.
플레이어를 밀어내는 것뿐 아니라
플레이어의 체력을 감소시키고
체력 게이지를 업데이트하는 것도 가능합니다.
체력의 감소를 나타내려면 체력 게이지의
가로 길이에서 감소한 부분을 빼며
총 체력 대비 현재 체력의 비율을 찾아
녹색과 빨간색의 색상 알림을 사용하여
나타냅니다.
체력 게이지는 게이지의 윤곽과 게이지 본체,
즉 두 개의 스프라이트로
구성되어 있습니다.
이 체력 게이지는 포토샵에서 디자인된 다음에
두 가지 개별 요소로 내보내진 것입니다.
이 스프라이트의 가져오기 설정에서
축을 그래픽 왼쪽 중간으로 설정하면
값이 낮아질 때 왼쪽으로 줄어들게 됩니다.
이 두 개의 스프라이트는 플레이어를 쫓아가도록 만드는
단순한 스크립트를 가진 빈 상위 게임 오브젝트에
속해 있습니다.
플레이어 오브젝트의 위치와 같은 위치에
설정하면 이것이 가능합니다.
거기에 공개로 설정한 오프셋을 통해
Inspector에서 조절할 수 있습니다.
플레이어의 체력이 0이 되면
충돌체를 트리거로 설정하여
레벨에서 떨어지게 만듭니다.
그리고 Sprite Renderer를
게임의 가장 앞쪽에서 렌더링하도록 만드는 UI Sorting layer에 위치시켜
렌더링의 가장 앞으로 플레이어를 이동시킵니다.
플레이어 사망 시 모자와 총이 사라지는 Death와
Falling이라고 부르는 두 개의 애니메이션이
마련되어 있습니다.
Death 애니메이션이 끝나면
애니메이터의 전환 조건인 Exit Time에 따라
Falling으로 자연스럽게 바뀝니다.
마지막으로 Death 시퀀스 중 플레이어가 캐릭터를
이동하거나 총을 쏘지 못하도록 하기 위해
PlayerControl 및 Gun 스크립트를 비활성화합니다.
Die 함수는 public으로 만들어졌으므로
플레이어가 물에 빠지는 경우와 같은 여러 경우에
호출할 수 있습니다.
플레이어가 물에 닿았을 때 게임을 초기화하기 위해
트리거 충돌체와 스크립트로 간단하게 구성된
KillTrigger 오브젝트가 있습니다.
게임 대부분의 경우 Remover 스크립트의 목적은
강에 빠지는 적 오브젝트를 제거하고
스플래시 애니메이션 및 사운드 효과의
인스턴스 생성에 있습니다.
그러나 이 트리거에서 플레이어가 감지되면
PlayerHealth 스크립트의 Die 함수를 호출합니다.
그리고 플레이어를 화면 밖으로 이동시키고
2초간 일시 중지한 뒤
코루틴을 호출하고 레벨을 다시 불러오는 동안
CameraTracking을 비활성화합니다.
이제 죽음에 대한 이야기는 그만하고
생존과 그에 필요한 도구에 대해
알아보죠.
이 게임에서는 플레이어에게 도움을 주는
2개의 상자가 하늘에서 떨어지는데 하나는 폭탄,
다른 하나는 체력을 보충하는 구급 상자가 들어 있습니다.
이 상자는 상자와 낙하산 이렇게 두 개의
부분으로 구성되어 있습니다.
이 두 요소는 빈 상위 오브젝트에 속해 있어
그룹으로 애니메이트할 수 있습니다.
낙하산의 중심이 상위 오브젝트의 중심에 놓이도록
두 개의 스프라이트를 위치시킵니다.
이로써 상자 달린 낙하산 전체가 지상으로
내려오는 것처럼 애니메이션이 좌우로 흔들리게 됩니다.
그리고 나서 rigidbody를 추가하여 중력에 의해
오브젝트가 지상으로 내려오게 만듭니다.
그리고 충돌체를 상자에 추가하여 상자가
지상에 닿고 플레이어가 상자를 수집하는 순간을
감지할 수 있도록 만듭니다.
상자가 지상에 닿자마자 낙하산이 작아지는
두 번째 애니메이션 상태로 전환합니다.
게임의 다른 부분과 마찬가지로 애니메이터는
오브젝트의 상태를 처리합니다.
기본적으로 floatDown 애니메이션 상태의
재생을 볼 수 있으나
트리거 Land가 True로 설정되면
Landing 상태로 전환됩니다.
스크립트에서는 태그를 통해 지상을 감지하는 onTriggerEnter 함수를
사용하여 이를 실시할 수 있습니다.
또한 상위 오브젝트에서 상자 자체를 분리하고
자신만의 rigidbody를 부여합니다.
그리하여 경사지에 착륙했을 때 사실적으로
배경과 상호 작용할 수 있도록 합니다.
일단 폭탄을 살펴볼까요?
폭탄 상자 수집은 상자에 연결된
BombPickup 스크립트를 통해 처리하게 됩니다.
상자를 수집 처리는 상자를 파괴하고
LayBombs라고 불리는 플레이어에 연결된
스크립트 안에 보유한 폭탄 수가 올라감으로써
처리됩니다.
LayBombs 스크립트는 단순히 플레이어가
폭탄을 가지고 있는지 확인합니다.
그리고 폭탄 프리팹 인스턴스를
생성합니다.
폭탄 프리팹에는 시한 퓨즈가 있는데
Explode 함수를 호출하기 전까지
BombDetonation 코루틴 내 Yield를 사용하여
대기합니다.
Explode 함수는 여러 가지 행동을 합니다.
먼저 bombLaid 변수를 초기화하여
다른 폭탄이 배치되도록 합니다.
그리고는 수집 생성 지점에 새로운 상자가
생성되도록 하고 정의된 폭발 범위 내
적을 처치하도록 합니다.
마지막 이 부분이 어떻게 작동하는지 살펴봅시다.
폭탄은 적에게 남아 있는 체력과 관계없이 치명적인 무기이므로
Physics.OverlapCircleAll을 사용하여
폭탄의 특정 범위 내에 있는
적으로 태그된 모든 오브젝트를 수집합니다.
그리고 나서 발견한 모든 적에게 foreach loop를 실행하여
체력을 0으로 설정하고 폭탄의 위치에서 적이 있었던 곳으로의
벡터를 찾아 해당 벡터 방향에
포스를 적용합니다.
일단 foreach loop이 완성되면
비주얼 효과를 재생하고 인스턴스화하고
폭발음을 위한 오디오 클립을 재생하며
폭탄을 폭발시킵니다.
폭발은 두 부분으로 되어 있습니다.
여기서 주요 부분은 잠시 나타났다가
사라지는 원이고
두 번째 부분은 로켓 폭발과 같은 스프라이트를
다시 사용하는 별의
파티클 시스템입니다.
효율성을 위해 해당 씬에서
파티클 시스템을 항상 유지하고 있으며
필요 시 원하는 위치로 시스템을 이동해
재생할 때는 코드를 사용합니다.
메모리에 파티클 시스템을 유지하고
게임을 효율적으로 만들어 줍니다.
이 씬에서 플레이어는
한 번에 하나의 폭탄만 던질 수 있습니다.
즉 폭발은 한 번만 발생한다는 것을 알고 있기 때문에
이렇게 작업할 수 있다는 것을 참고하시기 바랍니다.
씬에서 인스턴스를 생성했다가 제거하는 것보다
유지한 파티클 시스템을 재생하는 것이
더 효율적인 이유가 바로 여기 있습니다.
그러나 로켓 폭발의 경우,
한 번에 여러 번의 폭발이 발생할 수 있으므로
생성 후 제거해야 합니다.
이제 플레이어가 적을 처치하고 점수를 얻는 장면을
확인해 볼까요?
이것도 두 가지 부분이 있습니다.
100점 획득을 보여주는 점수 획득 애니메이션과
점수 증분을 보여주는 화면 상단의
점수 UI입니다.
점수 애니메이션은 1과 0, 두 개의 숫자 스프라이트로
구성되어 있습니다.
이것을 빈 상위 오브젝트에 속한 씬에 위치시키고
간단한 Destroyer 스크립트를 사용하여 애니메이팅하고,
애니메이션이 끝나면 씬에서 제거합니다.
타임라인 마지막에 애니메이션 이벤트를
위치시켜 스크립트의
Destroyer 함수를 호출합니다.
ScoreUI 자체는 사용자 정의 폰트와 스크립트로 이루어진
간단한 GUI 텍스트 요소로,
플레이어의 점수를 관리합니다.
Score 변수는 public 변수인데 이는 적이 사망했을 때
Enemy 스트립트에서 읽어 100점을 추가할 수 있음을
의미합니다.
지금부터는 적에 대해서 좀 더 자세히
알아보겠습니다.
게임에는 민달팽이처럼 생긴 단순한 녹색 괴물과
침공 중 자신을 보호하기 위해
함선을 타고 오는
두 종류의 외계인이 있습니다.
이 캐릭터들의 행동은 매우 흡사하기 때문에
같은 스크립트를 공유하지만
Inspector에서 각각의 이동 속도와 방어력을
public 변수들로 설정하여
다르게 만들 수 있습니다.
적들은 서로 다른 Walk 애니메이션을 가지고 있는데,
민달팽이는 움직이는 꼬리를 가지고 있고
함선을 타고 있는 외계인은 앞뒤로 움직이며 다가옵니다.
민달팽이는 Sprite Importer를 사용하여
그래픽의 꼬리 부분을
개별 스프라이트 요소로 정의합니다.
이를 통해 전체 스프라이트를 조정하지 않고도
꼬리를 개별적으로 움직일 수 있습니다.
축을 오른쪽으로 설정하면
그 점에서부터 꼬리가 늘어났다 줄어드는 애니메이션을
만들 수 있습니다.
이 캐릭터의 경우 눈꺼풀을 위아래로 움직이는데
Z값을 사용하여 여러 스프라이트를 서로 분류하여
눈이 눈꺼풀 뒤에 오고 눈앞에서 눈꺼풀 애니메이션이
연출되게 할 수 있습니다.
두 번째 적의 애니메이션은 앞뒤로 회전만 시키면 되므로
상당히 간단합니다.
적을 이동시키는 기법은
rigidbody의 속도를 설정하여 구동합니다.
벽과 같은 장애물에 맞닥뜨리면
충돌체와 겹치는 공간의 점을 확인하는
Physics.OverlapPoint 함수로 이를 감지합니다.
레벨 양쪽의 벽 또는 탑이 장애물로
태그되어 있습니다.
이 함수가 장애물을 감지하고 Flip 함수를 호출하면
적의 X 스케일이 역전되고
다른 방향으로 이동하게 됩니다.
로켓이 적에 부딪힐 때마다 적을 처치하는 경우,
스크립트는 로켓이 닿은 특정 적의
Hurt 함수를 호출합니다.
이 함수는 해당 적의 체력에서
1을 감소시킵니다.
그리고는 FixedUpdate 함수 내에서
적의 체력을 계속 감소시키다가
체력이 0으로 떨어지면 Death 함수를 호출합니다.
적이 사망하면 몇 가지 함수를 수행합니다.
먼저 2D 캐릭터가 움직이는
여러 스프라이트 오브젝트로 구성되어 있으므로
모든 Sprite Renderer를 비활성화합니다.
이는 사망한 캐릭터의 움직이는 요소들을
단일 스프라이트로 대체하기
위해서입니다.
주요 Sprite Renderer에 이와 같이 하려면
deadEnemy 변수에 할당된 스프라이트를 사용하도록
설정하면 됩니다.
이제 Score 스크립트의 public 변수를 사용하여
점수를 추가합니다.
적 사망 시 토크를 추가하여 적을 회전시킴으로써
적의 죽음에 시각적 효과를 추가합니다.
적이 죽을 때는 배경을 통과해 떨어져
강에 빠져야 하기 때문에
오브젝트의 모든 충돌체를 찾은 다음
IsTrigger 매개변수를 True로 설정합니다.
이로써 적이 배경 충돌체에 충돌하지 않고
떨어지게 됩니다.
앞서 설명한 Score 애니메이션의 인스턴스를 생성하기 전에
Death 오디오 클립 배열에서 하나를
선택하여 재생합니다.
사망한 적을 씬에서 제거하려면
killTrigger 오브젝트를 이용합니다.
killTrigger는 초반에 설명했던 것과 동일한 기능을 수행합니다.
플레이어가 아닌 오브젝트가 건드리면
스플래시 애니메이션이 작동되고 해당 오브젝트가 제거됩니다.
물에 빠질 때 나는 사운드 효과는
애니메이팅된 스플래시에 연결되어 Awake 작동 시
재생되는 오디오 클립입니다.
이로써 움직이는 오브젝트의 인스턴스가 생성되면
사운드가 바로 재생되는 것입니다.
게임 레벨을 마무리하기 위해서 배경을 몇 가지
움직이는 소품으로 꾸밉니다.
이를 통해 게임 배경을 좀 더 역동적으로 만들 수 있습니다.
날아가는 백조에 강둑을 따라 달리는 버스와 택시를
추가해 보죠.
먼저 백조부터 시작합니다. 스프라이트 시트에서 생성하고
포토샵에서 그린 다음 Inspector의
Multiple Sprite Mode 가져오기 설정을 사용하여 가져온
백조가 있습니다.
이러한 접근을 선택함으로써 유니티는 시트의 각 프레임을
선택하고 에셋의 상위 계층 아래에 속한 해당 프레임을
개별 스프라이트로 가져오는 작업을
자동화합니다.
이들은 애니메이션 프레임의 선형 집단으로
해당 스프라이트를 모두 드래그하여 씬에 넣기만 하면
유니티가 알아서 애니메이션 작업을 진행합니다.
드디어, 날아가는 백조가 배경 요소로
추가될 준비가 되었습니다.
이제는 백조에 rigidbody2D를 적용해서
화면을 가로질러 날아갈 수 있는 속도를
사용할 수 있도록 합니다.
버스와 택시처럼 백조도 프리팹으로 저장됩니다.
버스 및 택시 프리팹의 경우
차량의 본체와 바퀴를
Sprite Importer를 통해 분리하고
간단히 흔들리는 애니메이션을 적용합니다.
여기에 2d rigidbody도 적용하여
속도를 사용해 화면을 지나가도록 만들 수
있습니다.
3가지 소품인 버스, 택시, 백조가
화면에 나타나게 만드는
재사용 가능한 하나의 스크립트를 생성했습니다.
BackgroundPropsSpawner 스크립트 또한
화면에 나타나는 출현 빈도, 지정 속도 및
생성 위치를 처리합니다.
이는 우리가 동일한 스크립트로 3개의 Creator 오브젝트를
변경할 수 있다는 뜻입니다.
어떤 프리팹을 생성할지, 어떤 속성을 줄 것인지
변경할 수가 있는 것입니다.
자세한 내용은 스크립트의 코멘트를 확인하십시오.
마지막으로 배경에 역동성을 가미하기 위해
흐르는 구름, 강과 안개를 추가했습니다.
이들은 2개의 배경 스프라이트 인스턴스를 상위 오브젝트에 추가하여
만들었는데 화면을 가로지르며 서서히 진행하는 애니메이션을
사용했습니다.
이 애니메이션은 루프 기능으로
무한 반복됩니다.
지금까지 유니티 게임 제작 방법을 소개해 드렸습니다.
이 개요를 통해 유니티를 사용해 2D 게임을 제작하는 데
도움이 되었길 바라고,
앞으로 간단한 프로젝트 및 튜토리얼을 더 선보일
것을 약속드립니다.
Unity 4.3에 대한 여러분의 의견을 기다립니다.
그리고 곧 여러분이 만든 훌륭한 2D 게임을
만나볼 수 있길 기대합니다.
감사합니다.