저번에는 ChangeRoom 함수가 작동되는걸 확인해봤고, 이제 UI(위젯 블루프린트)랑 연결시켜서 입력가능 텍스트 위젯과 버튼으로 함수를 작동시켜볼 차례다.
그런데 블루프린트 위젯에서 Room에 대한 정보에 접근할 수 없었다.
그 해결책으로는 몇가지 방법이 후보군에 있었는데, 당장 생각할 수 있는 것으로는
1. 노드의 Get Actor of Class로 Room을 모아놓은 Spawner에 접근한다.
2. Spawner를 전역 선언해서 사용한다.
3. 이 위젯의 참조에 Spawner를 넣어놓는다.
가 있었다. 여기서 보통 1번을 쓴다고는 하는데, 유니티에서 싱글톤을 쓰느라 익숙해지기도 했고, Spawner가 월드에 하나밖에 존재하지 않으니까 싱글톤을 써도 될 것 같아서 2번으로 진행해봤다.
그렇게 만든 블루프린트가 작동을 하긴 하는데, 나중을 위해서 방의 Row와 Column 숫자를 Getter로 받아와서 사용하게 짰더니 접근이 잘 안됐다.
Get Instance에서 문제가 생겼다고 에러 메시지가 떴는데, 정작 Get Instance에서 따로 뻗어나간 것들은 잘 작동되는 상황. 그래서 일단 숫자 5를 하드코딩으로 박아놓고, 잘 작동하는 것을 확인한 이후에 대체할 수 있는 것을 좀 더 찾아봤다.
그래서 찾은 것이 UE5의 SubSystems가 있다. (공식 홈페이지는 여기 https://dev.epicgames.com/documentation/en-us/unreal-engine/programming-subsystems-in-unreal-engine?application_version=5.4)
각각 ~~Subsystem이라고 되어있는데, 이는 앞의 ~~ 부분과 사이클을 공유한다는 소리다.
UGameInstance가 생성되고, UGameInstanceSubsystem도 생성된다.
UGameInstance가 초기화되면, UGameInstanceSubsystem도 Initialize()가 호출된다.
UGameInstance가 shut down시, UGameInstanceSubsystem도 Deinitialize()가 호출된다.
읽으면서 곰곰이 생각해봤는데, 이런 게임 인스턴스 부분은 로비로 나가도 유지되는 환경설정 같은 것을 만들 때나 유효한 것 같지, 여기서 쓰기는 부적합 한 것 같다는 생각을 했다.
나중가면 로비나, 세이브 파일 선택 등도 만들 수 있을텐데 게임 실행이후 바로 만드는 것이 맞나? 라고 물어보면 모르겠다.
오히려 UGameWorldSubSystem(월드 시작시 같이 진행)이나 UGameLevelSubStstem(레벨 시작시 진행)이 더 어울리지 않을까? 라는 생각이 들었다. 결국 Spawner는 월드에 배치된 방과 배치에서 빼낸 유닛들을 관리하는 용도기 때문이다.
그래서 결국 1번으로 다시 제작했다. 결과물은 아래 사진과 같다.
저번에 만들었던 Room 소환 노드를 복사해와서 적절히 만져주면 끝.
유닛 스폰 장소인 Location값을 건들지 않아서 제 자리에 겹쳐 소환되지만, 어차피 로그로 확인할거니까 괜찮다.
다만 Unit은 Room이나 DungeonCore(Spawner 블루프린트)에 항상 귀속되어 있는 상태이므로, Room에 코드상으로 유닛을 추가, 제거하는 함수를 따로 만들어주자. 소속될 곳에도 Unit을 저장하는 배열을 만들어주자.
그러니까 Room과 Spawner에 Unit 클래스의 배열을 추가하고, Unit 클래스에는 현재 속해있는 곳을 추적하는 변수를 추가해주면 될 것 같다.
여기서 순환 종속때문에 잠깐 꼬였는데, 전방선언으로 어떻게 잘 해결했다. 더 예쁜 구조를 만들 수 있으면 좋겠는데...
Unit에 추가된 것은 현재 배치상태인가를 확인하는 변수와 유닛 소속을 설정, 해제하는 함수 둘.
bool bIsInSpawner;
void SetCurrentRoom(ARoomBase* NewRoom);
void UnSetCurrentRoom();
이제 유닛이 어느 방에 소속되어 있는지 확인할 수 있다.
유닛 소속을 Set 하는 것은 버튼 이벤트를 통해 확인한다고 하고, Unset은 어떻게 확인해야할까?
나중에 게임이 굴러갈 때를 생각해보면 Room이 변경되거나 파괴될 때 안의 유닛과 함정들이 전부 해제되고, 배치 물품이 아닌 소지품으로 다시 돌아올 것이다. 그러니 RoomBase 클래스의 방 변경에 맞춰 작동하게 만들어보자.
//유닛관리
UFUNCTION(BlueprintCallable, Category = "Unit 관련")
void AddUnitInRoom(AUnit* Unit);
UFUNCTION(BlueprintCallable, Category = "Unit 관련")
void RemoveUnitInRoom(AUnit* Unit);
//방 변경, 해제 등의 일에서 구성 요소 반환 함수
UFUNCTION(BlueprintCallable, Category="Room 관련")
void MoveUnitsToSpawner();
UFUNCTION(BlueprintCallable, Category="Room 관련")
void MoveTrapsToSpawner();
방 안 유닛의 추가, 제거. 그리고 방이 사라질 때 Spawner로 유닛의 귀속을 바꾸는 함수들.
잘 작동한다.
다음에는 위젯 부분을 도와주기로 한 친구의 작업물을 보고, 서로 그동안 한 것을 공유할 생각이다.
그러기 위해서는 여러가지 실험용으로 작성한 코드를 좀 정리하고, 설명하는 문서가 하나 필요할 것 같다.
'Unreal' 카테고리의 다른 글
[04] Actor Spawn, Algo/Sort (0) | 2024.08.15 |
---|---|
[03] Pawn C++ Class (0) | 2024.08.02 |
[02] Unreal Engine Learning (1) | 2024.05.16 |
[01] Unreal Engine Learning (0) | 2024.05.01 |