본문 바로가기
tips/유니티 게임만들기

유니티 강좌 5 - 총알 피하기 5/9. 버튼 이벤트와 Canvas

by 디지털 수공업자 2021. 3. 17.
반응형

 

1. Button 오브젝트와 Canvas

플레이어를 이동시킬 조이스틱은 아날로그 스틱형태로 만들기엔 내용이 아직 복잡할 수 있으니, 간단한 십자 버튼 형태로 만든다. GameObject > UI > Button으로 씬에 버튼 게임오브젝트를 하나 생성한다.

 

이번에 생성한 버튼 게임오브젝트는 지금까지 만들었던 게임오브젝트들과 다른 경로에 생성이 되었다.
GameObject > UI 메뉴에 있는 게임오브젝트들은 모두 위와 같이 Canvas라는 게임오브젝트의 하위에 등록된다. 

Canvas안에 있는 Button 게임 오브젝트의 Inspector를 보면, 최상단에 있는 콤포넌트가 Transform이 아니고 Rect Transform이다. Transform은 3D 공간상의 좌표값을 가지고 있는 콤포넌트이고, Rect Transform은 2D 공간상의 좌표값을 가지는 콤포넌트이다.

지금까지 만들어온 내용에서 2D 스프라이트로 player와 총알을 표현했지만, 유니티의 기본 공간은 3D공간이고, 2D게임을 만들 때는 3D 공간상에서 z축 하나만을 고정하는 것이라서, 애초에 지금까지 해온 모든것들에 붙어있던 Transform콤포넌트의 position이나 rotation등의 모든 값이 x, y, z 세 값을 가지고 있었다.

그런데 게임에서 보통 UI로 부르는 인터페이스들은 배경이나 캐릭터에 의해 가려지는 일이 없는 것으로 간주하여 모든 공간상의 이미지 또는 모델링들을 덮으며 보여진다. 이때 모든 화면을 덮는 레이어로 Canvas를 사용하며, UI의 모든 요소들은 이 Canvas의 하위에 등록하여 항상 화면의 최상단 레이어에 표시하여 가려지지 않게 할 수 있다. Canvas안에 등록되는 모든 UI 요소들은 2D로 표시되며 Transform 대신 Rect Transform을 사용해 가상의 화면영역인 Canvas내의 좌표값을 가지게 된다.

Canvas의 Inspector에서 Canvas콤포넌트의 몇 가지 항목을 수정한다.
Render ModeScreen Space - Camera로 변경하고 그 아래에 있는 Render Camera의 오른쪽 항목에 Heirarchy의 Main Camera 오브젝트를 드래그하여 넣어준다. Canvas Scaler콤포넌트에서는 UI Scale ModeScale With Screen Size로 변경하고 Reference Resolution을 요즘 많이 사용하는 QHD 사이즈로 1440에 2560으로 변경한다. Screen Match ModeExpand로 수정하고나면, 씬에 커다랗게 보이던 버튼이 작아진 것을 볼 수 있다.

위에서 설정한 내용은 대충 Canvas의 크기를 게임의 카메라 크기에 맞추고, 기준이될 해상도를 1440x2560으로 설정하였으며, Canvas가 기준 해상도보다 크거나 작아질 때 화면을 어떻게 맞춤할 것인가에 Expand를 설정하여 빈 공간에 여백을 남기지 않고, 화면을 꽉 채우도록 Canvas 비율을 변경한다는 정도의 내용이다. 여기에선 자세히 몰라도 설정만 위와 똑같이 하고 넘어가자. 이후에는 변경할 일은 없다.

Hierarchy에서 Main Camera를 선택하고 씬창의 좌측 상단에 있는 2D버튼을 눌러 끄면 씬의 내용이 입체로 전환된다.

마우스 왼쪽 드래그를 하면 화면을 이동, Alt키를 누르로 마우스 왼쪽 드래그를 하면 카메라의 회전, Alt키를 누르고 마우스 오른쪽 드래그를 하면 확대/축소 등의 움직임으로 앵글을 바꾸어가며 확인해보자.

세 개의 화살표가 그려진 중심에 작아서 잘 보이지 않지만 카메라 아이콘이 있다. 아이콘을 중심으로 초록, 빨간 화살표가 뻗은 방향으로 펼쳐진 면이 카메라 영역이다. 파란화살표쪽으로는 카메라가 잡아낼 수 있는 깊이이 공간이며, 카메라 육면체 중간쯤에 있는 면은 Canvas이다. 

Canvas콤포넌트로 돌아와 Plane Distance항목의 값을 5로 변경해보자. Main Camera를 선택해보면 Canvas가 player오브젝트보다 카메라에 가까워진것을 확인할 수 있다. 이와같이 카메라와 Canvas사이에는 다른 물체가 오지 않도록 조절한다.

 

2. Button

Hierarchy에서 Button을 선택하고 키보드의 F를 누른다. 씬의 공간 어디에 있던지, F키를 누르면 선택된 오브젝트가 씬의 가운데에 보일 수 있도록 포커싱해준다.

Button의 Inspector에 Rect Transform에는 해당 오브젝트의 크기나 위치를 설정하는 기준이 여러 개 준비되어 있다. 좌측 상단에 빨간 십자 라인이 그려진 부분을 Anchor Preset이라고 하여 기준점을 미리 설정해놓은 옵션이 있는데 이 그림이 이 위와 동일하다면 그 옆에 Width에 400, Height에 200을 입력한다. 프리셋이 위와 다르다면 그림을 눌러 같은 모양을 선택해주고 값을 입력하자.
이제 가로 400픽셀 세로 200픽셀의 크기를 가진 버튼이 되었다.

Button게임오브젝트에 기본으로 붙어있는 Button콤포넌트는 이 게임오브젝트를 버튼으로서 작동하도록 만들어준다. 게임을 실행하고나서 이 버튼을 클릭하면 클릭했음을 감지한다. 총알 게임오브젝트에서는 Sprite Renderer 콤포넌트가 하던 역할을 Canvas내에서는 Image가 대신하여 이미지를 표현해준다.

Button오브젝트 안에는 Text오브젝트가 있다. 여기에 있는 Text콤포넌트의 Text항목에 글씨를 적으면 게임화면에 글씨를 표현해준다. UP이라고 입력하고 아래의 Font Size60을 입력하자.

 

3. 게임오브젝트 복제

Button오브젝트를 선택하고 Control + D (맥 Command + D) 키를 누르면 오브젝트가 복제된다. 복제된 오브젝트는 이름 뒤에 (1)이 붙어 있다.

버튼을 복제하여 총 4개의 버튼을 만들고 오브젝트의 이름을 button_up, button_down, button_left, button_right으로 변경한다, 각 버튼 오브젝트 하위에 있는 Text콤포넌트를 수정하여 각 버튼에 표시되는 글씨도 UP, DOWN, LEFT, RIGHT으로 변경한다. 물론 한글을 사용해도 무방하다.
버튼의 위치는 위와 같이 각 오브젝트를 선택하고 씬에 나타나는 화살표를 당겨 적당히 배치하고 수치로 정학하게 맞추려면 각 오브젝트의 Rect Transform 콤포넌트에 있는 Pos XPos Y값을 수정하여 조정한다. 이 좌표값은 게임화면의 한 가운데를 기준으로 한다.

 

4. 플레이어의 이동 스크립트

Player.cs에 위와 같이 네 방향의 버튼을 눌렀을 때 호출할 함수를 만든다. 각 함수의 맨 앞에는 2편에서 언급했던 접근지정자로 public을 붙여준다. public을 붙임으로써 이 함수를 이 스크립트 밖에서도 접근하여 호출할 수 있게된다.

tansform은 이 스크립트가 콤포넌트로 사용되는 게임오브젝트의 Transform콤포넌트이며, Translate( )는 Transform클래스가 가진 물체를 이동시키는 함수이다. Translate에는 Vector3값을 전달해야하고, Vector3는 x, y, z 세 값을 변수로 가지는데, 그 세 값이 이미 지정되어 있는 변수가 있다.
Vector3.upVector3(0, 1, 0)과 같다. x와 z값이 0이고 y값만 1이므로, Vector3.up으로 이동한다는 것은 y축으로 +1만큼 이동한다는 의미가 된다. 나머지도 같은 방식으로 버튼을 누를 때 이 함수를 호출하면 해당 방향으로 player가 이동하게 된다.

 

5. Button 이벤트와 스크립트 연결

각 버튼의 Button콤포넌트 아랫쪽에 있는 OnClick( ) 항목 오른쪽 아래에 있는 + 모양 버튼을 누르면 비어있던 슬롯에 버튼들이 나타난다. 그 왼쪽 Runtime Only 바로 아래의 공간에 Hierarchy에 있는 player 게임오브젝트를 드래그하여 등록하고, 오른쪽 위의 No Function을 눌러 방금 연결한 player 게임오브젝트에 있는 Player콤포넌트를 고른 뒤 그 안에서 선택할 수 있는 리스트 중에 조금 전 작성했던 함수들에서 방향이 맞는 함수를 골라준다.

각 방향 네 개의 버튼 모두 동일한 과정으로 함수를 연결해준다.

실행하고 Game창에서 버튼을 눌러보면 player가 원하는 방향으로 움직인다.
Button콤포넌트에서 함수를 연결했던 이벤트 항목은 OnClick이었다. 클릭은 마우스 버튼을 뗄 때 이벤트가 발동하므로 위에서 한 방법은 꽤나 사용감이 불편하다. 지금 사용한 OnClick으로 함수를 호출하는 방식은 UI에서 사용하도록 하고. 사용감을 조금 개선해보자.

 

6. Event Trigger로 이벤트 개선

이제는 버튼을 누르고 있는 동안 player가 계속 움직이도록 변경할 것이다. button_up 게임오브젝트의 Inspector 맨 하단에 Add Component 버튼을 누르면 나타나는 풀다운 메뉴의 윗 부분에 trigger를 입력한 뒤 나타나는 Event Trigger를 누른다.

추가된 Event Trigger콤포넌트에 있는 Add New Event Type 버튼을 누르고 PointerDown을 선택한다. PointerDown은 마우스 버튼을 누르고 있는 상태를 의미한다. OnClick의 경우에는 누를 때는 아무일이 일어나지 않고, 뗄 때 함수가 호출되지만, PointerDown을 사용하면 버튼을 누를 때 이벤트 호출이 일어난다.

Event Trigger 콤포넌트에 나타난 이벤트 슬롯은 Button 콤포넌트에 있는 OnClick슬롯과 똑같이 생겼다. 아까와 마찬가지 방법으로 Player 게임오브젝트를 등록하고 Press_up( ) 함수를 선택해준다. 아까 작성했던 Button콤포넌트의 OnClick에 연결했던 이벤트- 버튼을 눌러 삭제한다.

 

7. Component 복사

Event Trigger 콤포넌트 이름에 마우스 오른쪽 클릭을 하고 Copy Component 를 선택한다.

button_left 게임오브젝트를 선택하고, Button 등 콤포넌트 이름에 마우스 오른쪽 클릭을 하고 Paste Component As New 를 선택한다.
위에서 추가했던 Event Trigger 콤포넌트가 함수 연결된 정보까지 함께 추가될 것이다. 여기에서 연결된 함수만 맞는 방향으로 변경하고, 나머지 right와 down버튼에도 동일하게 작업해준다. 마찬가지로 모든 버튼에서 OnClick( ) 이벤트는 삭제한다.

 

8. 스크립트 개선

Player.csstring형 변수 dir을 선언한다.

Update( )에는 위와 같은 조건문을 작성한다. 버튼을 눌렀을 때 호출되는 각 함수에서는 dir 변수에 방향에 대한 문자열을 변경해줄 것이다. 변경된 문자열이 담긴 dir 변수를 Update( )에서 매 프레임마다 검사를 하고 조건이 맞는 경우에 각각 이동 명령을 준다. 이전 편에서 다룬 조건문에서는 else if 가 한 번만 등장했었지만, 위와 같이 무한하게 연결하여 조건 검사를 할 수 있다.
이제 무엇을 해야할지 대충 감이 왔을 것이다.

예상대로 위에서 작성했던 각 함수에 들어있던 player이동 스크립트를 각 조건에 맞는 곳으로 가져온다.
이제는 버튼을 누르면 매 프레임마다 Translate( ) 가 실행되므로 예상보다 이동속도가 빠를 수 있으니, Translate( )에서 전달하는 Vector3 에 0.1을 곱하여 값을 10%로 축소시킨다.

기존에 작성했던 함수에는 dir 변수에 각 방향에 대한 문자열을 대입하는 것으로 정리한다.

이제 버튼을 누를 때 이벤트가 호출되므로 버튼을 누른채로 player를 움직일 수 있고, 매 프레임마다 조금씩 움직이므로 부드럽게 움직인다.

지금까지 작성된 Player.cs파일을 첨부합니다.

Player.cs
0.00MB

 

9. 미리해보기

여기까지 잘 따라왔다면 약간의 응용도 가능할 것이니, 버튼에서 마우스를 떼면 player가 이동하지 않고 멈추도록 해보자.
이에 관한 내용은 다음편에서 다루어 봅니다.

* 전 편에서 설명한 내용이 등장하면 설명을 스킵하고, 처음 나오는 내용은 한번씩 살펴보며 진행하여 점차적으로 프로젝트 진행 속도를 높여가고 있는데, 혹시나 설명없이 지나치고 있어서 연결이 잘 안되는 부분이 있으면 코멘트 주세요.

이 시리즈가 도움이 되셨다면 구독과 공감부탁드립니다.
이 시리즈가 계속 될 수 있는 힘이 될 것 입니다.


Translate( ) : docs.unity3d.com/kr/530/ScriptReference/Transform.Translate.html
Vector3( ) : docs.unity3d.com/kr/530/ScriptReference/Vector3.html

 

유니티 강좌 6 - 총알 피하기 6/9. 콜리더와 충돌 감지

아래 내용은 5편에서 이어집니다. 1편 : boxwitch.tistory.com/180 5편 : boxwitch.tistory.com/185 총알 충돌체 만들기 이제 총알이 player에 부딪히면 충돌했음을 감지하여 게임을 끝낸다. 여기에서는 게임..

boxwitch.tistory.com



반응형

댓글