본문 바로가기

모바일 게임 개발/[입문]브러쉬유

16. 브러쉬유: UI 기능 구현(1)

 

 

# 이번 시리즈를 마치면 얻게 되는 것

 

 

물감 튜브 드래그 앤 드롭

 

serviceapi.nmv.naver.com

이번 시리즈(?)를 마치면 위 영상에서처럼 물감 튜브(ItemWidget)를 슬롯(SlotWidget)에 드래그 앤 드롭으로 배치할 수 있게 될거예요. 진행 순서는 아래와 같아요.

1. 물감 튜브 생성 로직 구현

2. 드래그 앤 드롭 기능 구현

3. Master 위젯 블루프린트 로직 일부 구현

 

 


# 물감 튜브 생성

    + 생성시 물감 색상 정하기

 

게임 상에서 물감 튜브를 생성할 때, 색상 값을 전달해서 원하는 색의 물감 튜브가 만들어지게 해보겠습니다.

1. ItemWidget을 여세요. 그리고 우측 상단에 Graph(그래프 모드 이동 버튼)를 누르세요.

 

위젯 블루프린트 그래프가 나옵니다.

 

2. 변수를 하나 추가하세요. 이름은 Color로 지어주세요.

 

이제, 변수에 담을 데이터의 유형을 Linear Color 로 바꿔주어야 합니다.

3. 변수 이름 옆에 있는 버튼을 누르세요. 변수에 담을 수 있는 데이터 유형이 모두 표시됩니다.

하나의 변수는 하나의 데이터 유형만 담을 수 있어요. 우리는 색상 정보를 표현하는 데이터를 담을거에요. 그 데이터 유형의 이름은 Linear Color 에요.

4. Linear Color로 찾아서 선택하세요.

방금 우리가 한 것을 아래처럼 얘기할 수 있습니다.

 

 

"Linear Color 타입 변수를 선언했다."

 

 

변수의 '선언'이라고 하니 왠지 프래그래밍에 좀 더 가까워진 느낌이 듭니다.

5. 변수 타입은 디테일 패널에서도 변경할 수 있어요. 변수를 선택하고 디테일 패널의 Variable Type에서 똑같이 바꿔주면 됩니다.

Variable Type = 변수 유형

 

설명을 시작한 김에 조금 더 디테일 하게 들어가 볼게요. Linear Color 타입을 검색하지 않고 직접 찾으려면 Structure라는 카테고리를 열고 들어가서 찾아오게 될텐데요.

그 이유는 Linear Color가 구조체(Structure)이기 때문이에요. 구조체는 내부에 여러 타입의 변수를 가질 수 있어요. Linear Color는 어떤 타입의 변수들을 갖고 있는지 그 내부를 보여드릴게요.

방금 우리가 선언한 Linear Color 타입의 변수를 Get으로 그래프 위에 가져온 모습이에요. 아웃풋 핀을 우클릭 해서 Split Struct Pin 해보면,

이렇게 내부를 볼 수 있어요. Linear Color 는 4개의 변수를 묶어서 만든거였네요. 핀의 색깔이 연두색인것을 보니 변수의 타입은 실수를 저장할 수 있는 float이에요. 그리고 각 float 타입 변수에는 R, G, B, A 라는 이름을 붙여놨어요.

그래서 Linear Color 는 Red, Green, Blue 그리고 투명도를 결정하는 Alpha 값을 한번에 저장해서 운반할 수 있게 4개의 float형 변수를 묶어서 만든 구조체에요. 그리고 우리는 그 구조체를 변수로 선언했으니까 결국

 

 

"Linear Color 구조체 변수를 선언했다."

 

 

고도 할 수 있습니다. (첫번째 표현도 틀린 것은 아닙니다.) 아래에 변수와 구조체 변수에 대한 설명이 자세하게 나온 공식문서 링크를 걸어드릴게요.

 

 

블루프린트 변수

월드의 오브젝트나 액터에 대한 값 또는 레퍼런스를 담는 프로퍼티입니다.

docs.unrealengine.com

 

블루프린트의 구조체 변수

블루프린트 구조체 변수로 관련된 정보가 들어있는 다양한 데이터 유형을 저장할 수 있습니다.

docs.unrealengine.com

6. Color 구조체 변수의 Expose on Spawn(스폰 시 노출)과 Instance Editable(인스턴스 편집가능)을 체크하세요.

참고로 Instance Editable 옵션은 변수 목록에서 우측 눈 아이콘을 클릭해도 활성화 시킬 수 있어요.

눈을 뜨거라

 

7. 아래와 같은 노드망을 구성하세요.

노드망 구성할 때 알아야 할 내용

- Construct는 이 위젯이 만들어 지는 시점에 호출되는 이벤트에요. 액터의 BeginPlay 랑 비슷한거예요.

- Create Dynamic Material Instance 노드의 Parent를 PaintTube 머티리얼로 설정하세요.

- Set Vector Parameter ValueParameter NameColor로 바꾸는 것을 놓치지마세요.

- Set Brush from Material은 Get Image119 노드의 핀을 뽑아들고 만드세요.

이 노드망의 의미

1) 위젯이 처음 만들어질 때 머티리얼을 하나 만든다. (이렇게 실시간으로 만드는 머티리얼을 Dynamic Material Instance 라고 해요)

2) 머티리얼의 Color라는 이름의 Vector Parameter를 Color 구조체 변수의 값으로 변경한다.

3) image119의 그림을 방금 만든 머티리얼로 변경한다.

image119라고 하면 한번에 알아볼 수 없으니 다음 과정을 진행하기 전에 그 이름을 바꿔주겠습니다.

8. ItemWidget의 Designer 모드로 넘어가서 Image_119 선택하고, 그 이름을 Image_PaintTube로 바꾸세요.

 

노드의 이름도 자동으로 바뀝니다.

오 정말이네!

 


# 튜브 배치하기

 

물감 튜브에 색 입힐 준비가 끝났으니 SlotWidget에 물감을 실제로 생성하는 로직을 구현해볼게요.

1. Master 위젯 블루프린트를 열고 Graph 모드로 들어가세요.

Master 위젯 블루프린트
이벤트 그래프 등장

 

2. 우클릭 > Custom Event 검색 후 노드를 생성하세요. 이름은 AddTube로 지으세요.

3. 우선 슬롯에 넣을 위젯을 생성해야겠죠? Create Widget 노드를 만들고 ItemWidget을 선택하세요.

Color 구조체를 연결할 수 있는 핀이 생겼습니다!

우리가 앞서 ItemWidget의 블루프린트 속에 선언한 Color 구조체 변수에 대해 Expose on Spawn(스폰 시 노출) 옵션을 켜주었죠. 그렇기 때문에 ItemWidget을 만들 때 해당 변수에 값을 넣어줄 수 있어요.

4. 색깔은 AddTube를 호출할 때 받아오려고 해요. Create Item WIdget Widget 노드의 Color 핀을 뽑아들고 AddTube 이벤트 노드에 내려놓으세요.

이벤트 노드에 새로운 핀이 생겼어요. 이제 이벤트를 호출할 때 Color 구조체를 같이 넣어줄 수 있어요. 그리고 그 데이터는 이벤트 진행 과정에서 Create Item Widget Widget 노드에 전달됩니다!

여기서 잠깐,

위젯 생성 노드의 이름이 Widget Widget이라서 좀 거슬리네요. 이름을 바꿔주고 올게요. ItemWidget은 Item으로 바꾸고 SlotWidget은 ItemSlot으로 바꿀게요. (그냥 Slot은 하면 안됩니다. 오류가 생겨요)

깔-끔

됐습니다. 다시 Master로 돌아가보죠.

5. 이벤트 호출때 슬롯 위젯도 같이 전달할 수 있게 만들겠습니다. AddTube 이벤트 노드를 클릭하고 디테일 패널의 Inputs 카테고리 옆 + 를 누르세요.

누르고
누르고
찾고
이름까지 바꿔주세요.
노드에 Input이 하나 더 생겼어요

 

눈치 빠르신 분들은 이미 파악하셨겠죠? Input은 핀을 꽂아서 만들거나 직접 만드는 두가지 방법이 있습니다.

6. AddTube 이벤트의 Slot 핀을 뽑아 들고 검색창에 ItemSlot을 쳐보세요.

7. Cast To ItemSlot을 만드세요. 그리고 아래와 같이 연결하세요.

Cast To 노드는 일반적인 것을 구체적인 것으로 만들어 주는 노드에요. 이게 무슨말이냐면,

우리가 Slot 이라는 핀을 통해 받아온 것은 그냥 Widget 이에요. 그냥 위젯. 그런데 우리가 원하는 것은 위젯 중에서도 ItemSlot 이라는 특정한 위젯이죠. 그래서 그냥 Widget을 ItemSlot 이라는 구체적인 것으로 바꿔준 거예요.

이렇게 할 수 있는 이유는 ItemSlot이 UserWidget을 기반으로 만들어 졌고 다시 UserWidget은 Widget을 기반으로 만들어 졌기 때문인데요. 코딩을 배운 사람들은 이 관계를 이렇게 말하기도 해요.

 

 

 

ItemSlot은 UserWidget의 자식이다.

UserWidget은 Widget의 자식이다.

따라서 ItemSlot은 Widget의 '자손'이다.

Widget은 UserWidget의 부모다.

UserWidget은 ItemSlot의 부모다.

따라서 Widget은 ItemSlot의 '조상'이다.

 

(뒤에 클래스 라는 말을 붙이면 더 정확함)

 

 

 

근데 그냥 처음부터 ItemSlot으로 데이터를 넘겨주면 안되는걸까요? 그게 곤란한 이유는 조금 있다가 알려드릴게요.

8. Cast To ItemSlot 위젯의 As Item Slot 핀을 뽑아들고 Border를 검색하세요. GetBorder(_숫자)를 선택하세요.

뒤에 숫자가 없거나 다를 수 있어요.

이 작업은 ItemSlot 위젯 블루프린트에서 우리가 슬롯으로 쓰려고 만든 Border를 불러오는 작업이에요. 아래 사진을 참고하세요.

ItemSlot 위젯의 Border를 가져왔습니다.

9. Border(_숫자)핀을 뽑아들고 Add Child를 찾아서 만드세요. 그리고 노드망을 아래 그림처럼 마무리 하세요.

10. 이번엔 또 다른 Custom Event를 만드세요. 이름은 SetTubes에요.

11. Vector형 인풋을 하나 추가하고 Colors 라고 이름 붙이세요.

12. 오른쪽에 버튼을 눌러서 '배열'로 만드세요.

 

배열은 똑같은 데이터형들에 번호를 붙여서 모아 놓은 것이에요. 변수나 구조체와 마찬가지로 일반 프로그래밍에 있는개념이에요.

아래 링크는 언리얼 엔진의 블루프린트 안에서 배열을 어떻게 다루는지 알려주는 공식문서입니다.

 

 

블루프린트 배열

블루프린트 배열의 생성, 편집, 사용 관련 문서입니다.

docs.unrealengine.com

이제 SetTubes 이벤트는 동시에 여러개의 Vector 데이터를 배열 형태로 받아올 수 있게 됐어요.

13. Samples 변수를 Get 노드로 만드세요.

Designer 모드에서 확인할 수 있듯이 Samples는 ItemSlot 5개를 갖고 있는 Horizontal Box입니다.

슬롯 5개짜리 Horizontal Box

14. Samples 핀을 뽑아 들고 GetAllChildren 노드를 만드세요.

GetAllChildren 노드를 이용해 Horizontal Box 안에 들어있는 모든 '내용물'을 가져올 수 있어요. 여기서 그 내용물은 ItemSlot 일테지만 처음에는 그렇게 특정짓지 않고 가져옵니다. (매우 중요해요. ItemSlot의 형태로 가져오지 않아요!)

15. 내용물을 하나하나 꺼내볼까요? 구멍난 네모처럼 생긴 Return Value핀을 뽑아 들고 for each loop 노드를 만드세요.

연결이 되면 핀의 모양이 완전해집니다.

 

ForEachLoop 노드는 배열을 받아서 순서대로 내용물을 꺼내주는 노드에요. 아까 제가 배열속에는 내용물의 번호를 붙여서 저장한다고 했었죠. 그 번호 순대로 꺼내줍니다. 그리고 가장 첫번째 순서는 1번이 아니라 0번입니다.

16. AddTube라는 노드를 검색해서 만드세요. 그리고 Array Element를 AddTube의 Slot 핀에 꽂으세요.

이 노드는 우리가 만든 AddTube 커스텀 이벤트(Custom Event)를 호출하는 노드에요.

그리고 보시는 것처럼 이벤트를 호출할 때 Color와 Slot을 전달해줄 수 있게 되어있죠.

Color와 Slot을 전달받을 수 있어요

그런데 Slot이라고 이름을 지어놓고 데이터를 받아오긴 했는데, 사실 데이터를 전달할 때 까지는 ItemSlot형태가 아니에요. 그냥 Widget 형태죠. 그래서 AddTube 이벤트가 시작되고 나서 Cast To ItemSlot을 이용해 전달받은 데이터를 특정짓게 됩니다.

아래 그림에서 데이터가 흘러가다가 언제 바뀌는지 확인해보세요.

17. 이제 SetTubes 이벤트 노드에 만든 Colors 배열핀을 뽑아 들고 Get (a copy) 를 만드세요.

배열 안에서 지정된 번호에 저장된 데이터를 하나 가져오는 노드에요.

18. ForEachLoop 노드의 Array Index를 아래처럼 연결하세요.

19. Get의 아웃풋 핀을 AddTube 이벤트 호출 노드의 Color핀에 연결하세요.

두 데이터의 형태는 다르지만 내부적으로 호환을 해주기 때문에 연결할 수 있습니다.

20. 실행핀을 모두 연결하세요.

 


# 물감 생성 테스트하기

 

두 이벤트가 잘 작동하는지 테스트를 한번 해볼게요.

1. Master 위젯에서 Construct 이벤트를 만드세요.

2. SetTubes 이벤트를 호출하는 노드를 만드세요.

3. Colors 배열 인풋핀을 뽑아 들고 Make Array 노드를 만드세요.

4. Make Array 노드에서 Add pin+ 버튼으로 총 5개의 Vector를 만드세요. (4번까지 만들면 5개입니다.)

5. 0~1 사이에서 임시로 넣을 값 아무거나 넣으세요.

6. Play 버튼을 눌러서 확인하세요. (위젯 블루프린트의 툴바에도 Play 버튼이 있어요)

우왕굳 ​

 

테스트 성공입니다!

 


 

# 다음 장에서는

 

이제 다음 장에서 드래그 앤 드롭 기능을 구현할 준비가 된 것 같네요. 바로 들어가도 괜찮지만 아래에 관련 자료들을 몇개 준비해봤어요. 한번씩 보시면 큰 도움이 될거예요. (영상에 한글 자막은 없지만 따라하는데는 지장없답니다.)

 

 

드래그 앤 드롭 UI 제작

UMG 로 드래그 앤 드롭 가능한 UI 위젯을 만드는 법을 보여드립니다.

docs.unrealengine.com