UE4 Chapter 10-2. HUD : 몬스터 HP Bar
카테고리: UE4 Lesson 1
태그: UE4 Game Engine
인프런에 있는 황대희님의 언리얼 엔진4 3D 횡스크롤 게임 만들기 강의를 듣고 정리한 필기입니다. 😀
언리얼 엔진 공식 문서 https://docs.unrealengine.com/ko/index.html
🚖 몬스터의 HP Bar UI 만들기
몬스터의 상태 UI 를 나타낼 “CharHpBar” 위젯 블루프린트 추가
🚩 “CharHpBar” 위젯 블루프린트 디자이너 모드
게임 중, 몬스터 위에 띄울 것이기 때문에, 즉 3 D 공간에 띄울 것이기 때문에 Canvas Panel은 지워준다. 몬스터 Hp Bar 를 나타낼 progress bar는 Canvas Panel 같은 도화지 위에 그리지 않고 3 D 게임 월드 공간에서 몬스터 바로 위에 띄울 것이다.
ProgressBar_HP
- Progress - Percent 를 1 로 설정해주었다. 기본 상태를 100% 채워져 있는 상태로!
- Appearance - Fill Color 에서 채울 색 지정
Canvas Panel 없이 progress bar 만 있는 것을 볼 수 있다. 크기 조정은 몬스터 블루프린트에서 진행할 것.
🚖 HP Bar UI 가 몬스터를 따라다니게 하기
HP Bar UI를 몬스터의 컴포넌트로서 추가한다면?
게임 플레이 내내 좌측 상단에 플레이어의 HP가 표시되기 때문에 게임 인스턴스에서 플레이어 HP UI를 생성 및 띄우기 관리를 했었던 것과 달리 몬스터의 HP Bar는 항상 개개인의 몬스터 머리 위에 띄울 것이기 때문에 몬스터의 HP Bar UI를 몬스터의 컴포넌트로서 추가할 수 있을 것이다.
🚩 몬스터 블루프린트 뷰포트
Widget
컴포넌트를 추가한다.- Detail에서 User Interface 의
Widget Class
에서 위에서 만든 몬스터의 HP Bar UI 블루프린트인 “CharHpBar” 를 적용시켜 준다. Widget
컴포넌트의 Draw Size 로 크기를 조정해준다.
이렇게 위와 같이 몬스터의 HP Bar UI를 몬스터의 컴포넌트로서 직접 추가해줄 수 있지만 위와 컴포넌트로서 추가하면 생기는 문제가 있다.
- 몬스터가 회전하면 HP Bar UI 도 같이 회전하기 때문에 (컴포넌트니까)
- 몬스터가 90도 정도 회전한 상태면 HP Bar UI 가 안보이게 된다.
- 몬스터가 180도 회전하여 방향을 바꾼 상태라면 HP Bar 도 반전되게 된다. (깎이는 방향도 반전됨)
이처럼 HP Bar UI가 몬스터의 컴포넌트로 설정되어 따라서 회전하여 방향을 바꿀 때마다 위와 같은 문제가 발생한다. 컴포넌트다보니 몬스터에게 종속되기 때문이다. 따라서 “CharHpBar”를 직접적인 몬스터 블루프린트의 컴포넌트로 설정하는 방식은 사용하지 않을 것. Widget
컴포넌트 다시 삭제함.
HP Bar UI를 액터로 추가하고 이를 몬스터 머리 위에 독립적으로 띄움
1️⃣ 몬스터 머리 위에 스폰시키기
아래와 같은 방법을 사용하여 Hp Bar가 몬스터 머리 위에 따라다니게 할 것이다. Hp Bar는 몬스터의 구성 요소로서 종속되지 않으며 따라서 몬스터가 회전할 때 같이 회전하지도 않는다. 우선 컴포넌트가 아닌 몬스터와 상관없는 3D 공간의 독립적인 액터로서 띄울 것이기 때문에 “CharHpBarBP” 액터 블루프린트 클래스를 만든다.
- 독립적인 액터 “CharHpBarBP”
- 👉 “CharHpBar” 위젯 블루프린트를 띄울 Hp Bar
Widget
컴포넌트를 추가
- 👉 “CharHpBar” 위젯 블루프린트를 띄울 Hp Bar
- Hp Bar를 띄울 위치만을 나타낼, 몬스터 머리 위에 위치한 몬스터의 컴포넌트
Cube_HpBarPoseDummy
- 👉 이 컴포넌트의 위치에 “CharHpBarBP” 액터를 스폰할 것이다.
- 몬스터에 종속되지 않으므로 몬스터와 같이 회전할 일도 없을 것이며, 단순히 몬스터의 머리 위 위치만 제공하는 Dummy 컴포넌트를 만든 후 이 위치로부터 "CharHpBar" 위젯을 컴포넌트로 가지는 "CharHpBarBP" 액터를 스폰하는 방식으로 몬스터를 따라다니게 할 것이다!
- 👉 이 컴포넌트의 위치에 “CharHpBarBP” 액터를 스폰할 것이다.
🚩 “CharHpBarBP” 액터 블루프린트 뷰포트
- 이 액터는 “CharHpBar” UI 위젯을 띄울 용도로 사용될 것
Widget
컴포넌트를 추가한다. (HpBarComp)- 띄울 Widget Class는 “CharHpBar”
- 언리얼은 X 축이 앞방향이니까 이를 기준으로 알맞게 회전시킨다 (z축 -180도 회전해줌)
- Draw Size 로 위젯 크기 조절
🚩 몬스터 블루프린트
- 추가한 위 큐브 컴포넌트는 “CharHpBarBP” 액터의 스폰 위치가 되주기 위해 추가한 것.
- 몬스터에게 큐브 컴포넌트 추가
Cube_HpBarPoseDummy
- Collision은 꺼준다. (콜리전 프리셋 No Collision)
- 몬스터 머리 위에 위치할 수 있도록 위치와 크기를 조정한다.
- 위치 제공해주는 용도로만 쓸 것이기 때문에 큐브는 보이지 않아야 한다. 큐브는 게임 플레이시 보이지 않게 Rendering 에서 Hidden in Game 을 체크해준다. 이렇게 되면 에디터에서만 보이게 되고 플레이 중에는 보이지 않게 된다.
- “CharHpBarBP” 액터는 투명 액터라 이 작업 않해줘도 된다. 이건 큐브라서..
- 몬스터에게 큐브 컴포넌트 추가
몬스터가 생성되자마자(BeginPlay) 몬스터 머리 위에 위젯을 컴포넌트로 가지고 있는 "CharHpBarBP" 액터를 스폰한다. “CharHpBarBP” 액터와 몬스터 액터는 별개이기 때문에 “CharHpBarBP” 액터는 몬스터 머리 위에서 스폰될 뿐 몬스터와 같이 회전하지는 않는다.
몬스터 머리 위에 있는 몬스터의 큐브 컴포넌트 Cube_HpBarPoseDummy
의 위치를 받아와서(GetWorldLocation) 이 위치를 기반으로 Transform을 생성하고(Make Transform) 이 Transform 으로 “CharHpBarBP” 액터를 생성한다.(SpwnActor)
이제 게임을 플레이해보면 몬스터 머리 위에 Hp Bar가 생성된다. 그러나 아직 몬스터를 따라다니는 단계는 구현 X
2️⃣ 몬스터 따라다니게 하기
매 프레임마다 몬스터의 Cube_HpBarPoseDummy
위치를 받아 와 이 위치로 “CharHpBarBP” 액터 위치를 업뎃해야 한다.
🚩 “CharHpBarBP” 액터 블루프린트
함수 UpdateLocation
를 만든다. 몬스터의 Cube_HpBarPoseDummy
위치를 입력받을 Vector 매개 변수를 만들고, “CharHpBarBP” 액터 위치(self)를 입력 받은 파라미터 값으로 설정하는 일을 한다.
🚩 몬스터 블루프린트
“CharHpBarBP” 레퍼런스 변수를 만들고 스폰하여 생성한 CharHpBarBP
액터를 “CharHpBarBP” 레퍼런스 변수에 저장한다. (UpdateLocation
함수를 호출하기 위해)
매프레임마다(Tick) 스폰했던 CharHpBarBP
액터(타겟)의 UpdateLocation
함수를 호출한다. 이 함수의 파라미터로는 Cube_HpBarPoseDummy
위치를 넘겨 CharHpBarBP
액터의 위치를 매 프레임마다 Cube_HpBarPoseDummy
위치로 세팅한다.
🚕 HP 를 HP Bar UI 에 적용시키기
🚩 “CharHpBarBP” 액터 블루프린트
“CharHpBar” 위젯 블루프린트의 몬스터 HP Bar 를 나타내는 Progree Bar Hp
를 가져올 것이다. 이는 한번만 저장해두면 되기 때문에 액터 활성화시 BeginPlay 이벤트에서 한번만 작업해놓는다.
“CharHpBarBP” 액터는 “CharHpBar” 위젯 블루프린트를 컴포넌트로서 가지고 있을 뿐, “CharHpBar” 위젯 블루프린트인 것은 아니기 때문에 바로 Progree Bar Hp
를 가져올 순 없고 아래와 같은 과정을 거쳐야 한다.
- “CharHpBar” 위젯 블루프린트를 참조하는
HpBarComp
컴포넌트를 “CharHpBar” 위젯타입의 오브젝트로서 리턴한다.- Get User Widget Object 👉 위젯 컴포넌트를 오브젝트로서 리턴한다.
- 오브젝트로서 리턴하는 이유는 “CharHpBar” 위젯 블루프린트의
Progrees Bar
를 가져오기 위해서. (컴포넌트 상태로는 못 가져오나보다.)
- Object로서 가져왔으니 “CharHpBar”로 형변환한다. (다운 캐스팅)
- As Char Hp Bar에서 “CharHpBar”의
Progrees Bar
를 검색하여 Get으로 가져온다. ProgressBar Hp Bar
변수를 만들고(타입은 Progress Bar 레퍼런스)이 변수에 “CharHpBar”의Progrees Bar
를 저장한다.
Update Hp Bar
함수를 만든다. 이 함수로 ProgressBar Hp Bar
(“CharHpBar”의 Progrees Bar
가 저장되있음)의 퍼센트 값을 설정해줄 것이다. 파라미터는 HP, Max Hp 를 받으며 이 둘을 나눈 값으로 프로그레스 바 값으로 설정해주는 함수.
🚩 몬스터 블루프린트
- 몬스터가 데미지를 입을 때 발생하는 Any Damage 이벤트 부분
CharHpBarActor
(“CharHpBarBP” 액터)의Update Hp Bar
함수를 호출하여 Progress bar 업데이트- 이제 몬스터는 맞을 때마다 Hp Bar가 깎이게 된다.
- 몬스터가 데미지를 입을 때 발생하는 Any Damage 이벤트 부분
- 몬스터가 죽으면
CharHpBarActor
(“CharHpBarBP” 액터)도 같이 삭제한다. (Destroy Actor)
- 몬스터가 죽으면
몬스터가 맞을 때마다 Hp Bar가 깎이는 것을 볼 수 있다.
런타임 에러 수정
강의에는 언급되지 않았지만(다다음 강의에서 말씀해주셨음) 계속 런타임 에러들이 쭉 발생해서.. 위와 같이 수정해서 해결했다. 위에서 몬스터가 죽으면 CharHpBarActor
도 Destroy 시켰기 때문에 몬스터 죽고난 후 Tick 이벤트에 의하여 다음 프레임에서 Update Location 함수를 실행시키고자 할 때 런타임 에러가 발생했다. CharHpBarActor
는 파괴되어 없기 때문이다. 따라서 위와 같이 IsValid를 통해 CharHpBarActor
가 유효할 때만 Update Location 함수를 실행하는 것으로 변경해주었다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기