어제까지 급하게 TGS 참가 심사용 빌드를 뽑느라 벨로그에 글 쓸 정신이 없었다. 잡히는대로 쳐내느라 뭘 했는지 정확히 기억은 안나지만, 튜토리얼 UI 구현정도는 한번 정리하고 다시 시작하는게 맞을 것 같아 열심히 써보려고 한다 :)
텍스트의 길이에 따라 크기가 조절되도록 하는게 관건이었는데, 간단할거라 생각했지만 여기서 꽤나 헤맸다.. 어쨌든 이것저것 찾아보고 해보면서 결론적으로는 잘(?) 구현하긴 했다. 다음에 만들땐 좀 덜 헤맬 수 있을까..
이번에는 HP Bar처럼 따로 위젯 파일을 나누지 않고 기존 Player HUD에 만들어주었다. Overlay 패널에 Image와 Vertical Box를 넣고, Vertical Box에는 Text 두개(타이틀, 본문)를 배치해주었다.
본문의 내용에 따라 늘어나게 해야하므로 Size To Content를 체크해주었다. 이미지 크기는 본문에 한줄이 무조건 채워져 있다고 가정하고 X 300 / Y 70으로 지정해줬음!
테두리가 있는 상자 이미지다보니, 본문 크기에 맞춰 이미지가 늘어날 때 이미지가 깨지고 늘어나는 문제가 있었다.
Appearance의 Draw As와 Margin을 사용해주면 해결할 수 있다. Draw As를 Box로 선택해주면 마진으로 설정된 부분은 고정되고 나머지 부분은 Stratch되어 채워지는 것 같다.
이미지가 늘어나도 테두리가 훨씬 깔끔한걸 볼 수 있다.
텍스트 주변에 상하좌우 여백이 있는게 훨씬 보기 좋을 것 같아 상하좌우 패딩을 20씩 주고, 꽉 채워진 정렬을 위해 Horizontal & Vertical Alignment를 모두 Fill로 설정해주었다.
-> 타이틀 텍스트 설정
-> 본문 텍스트 설정
사실.... 정확히 어떻게 기능하는지 잘 모르고 써서 뭐 하나만 잘못 건들이면 삐꾸가 나버린다 ㅎㅎ.. 나중에 공부해서 제대로 만들어봐야지..
그래도 일단 잘 동작하잖아요ㅠㅠ
안내창에서 타이틀 텍스트와 본문 텍스트만 건들이면 되므로 이 두개만 변수로 만들어주고 C++과 연동해주었다.
// playerHUD.h
UPROPERTY(meta = (BindWidget), VisibleAnywhere, BlueprintReadOnly, Category = "Quest")
TObjectPtr<class UTextBlock> TitleText;
UPROPERTY(meta = (BindWidget), VisibleAnywhere, BlueprintReadOnly, Category = "Quest")
TObjectPtr<class UTextBlock> ContentsText;
void SetQuestText(FString InTitle, FString InContents);
// --------------------------------
// playerHUD.cpp
void UPlayerHUD::SetQuestText(FString InTitle, FString InContents)
{
TitleText->SetText(FText::FromString(InTitle));
ContentsText->SetText(FText::FromString(InContents));
}
playerHUD
클래스에 멤버변수와 함수를 선언해주고, 세팅하는 코드를 만들어주었다.
void AQuestManager::RequireSetQuestUI()
{
if (!QuestList.IsValidIndex(CurrentQuestIndex)) return;
FQuest CurrentQuest = QuestList[CurrentQuestIndex];
if (CurrentQuest.GoalCount != 0)
{
FString Info = TEXT(" ") + FString::FromInt(CurrentQuest.Count) + TEXT("/") + FString::FromInt(CurrentQuest.GoalCount);
CurrentQuest.Description += Info;
}
MyOwner->SetQuestUI(CurrentQuest.Title, CurrentQuest.Description);
}
퀘스트 매니저에서 현재 퀘스트 정보를 담아 GameMode에게 UI를 변경해달라는 요청을 보내면,
void ATrapperGameMode::SetQuestUI(FString Title, FString Contents)
{
for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
ATrapperPlayerController* PlayerController = Cast<ATrapperPlayerController>(Iterator->Get());
if (PlayerController)
{
PlayerController->MulticastRPCQuestSetting(Title, Contents);
}
}
}
게임모드에서 플레이어 컨트롤러에 접근해 멀티캐스트 함수를 호출해준다.
void ATrapperPlayerController::MulticastRPCQuestSetting_Implementation(const FString& InTitle, const FString& InDescription)
{
if (IsLocalController() && PlayerHudRef)
{
PlayerHudRef->SetQuestText(InTitle, InDescription);
}
}
그럼 RPC를 수신한 플레이어 컨트롤러에서 플레이어 허드에 접근해 퀘스트 텍스트를 세팅해주는 식!
퀘스트 위치에 이펙트 출력, 맵에 투명 벽과 트리거 박스 배치, 게임모드 버그 수정, 기획의 Q/A를 위한 편의성 기능 제공, 리스폰 UI 초기화, 함정을 사용할 때 아이템이 사용되게 하는 서버 처리, 클리어/게임오버 UI 및 처리, 제단 HP 등 게임의 완성도를 위해 이것저것 했던 것 같다.
이제 급한 빌드는 끝났으니, 해왔던 것처럼 하나씩 정리해가며 진행해야지 :)