슬슬 탄약 시스템과 재장전 시스템을 만들 때가 된 것 같다.
장전 로직의 핵심을 정리해보자면 다음과 같다.
- 총을 발사할 때마다 탄약 개수가 1씩 줄어든다.
- 현재 탄약이 0이면 발사하지 못한다.
- 장전을 통해 현재 탄약을 최대 탄약으로 채우고, 전체 탄약에서 채운 양을 제외한다.
실은 이러한 기본적인 것들은 이미 Gun 클래스에 구현해두었다.
void AGun::Fire(FVector& StartPoint, FVector& Direction)
{
CurrentAmmo = FMath::Clamp(CurrentAmmo-1, 0, MaxAmmo); // 현재탄약 -1
}
/*
* MaxAmmo: 탄창에 들어가는 최대 탄약 개수
* CurrentAmmo: 현재 탄창에 들어있는 탄약 개수
* ReloadingAmmo: 전체 탄약 개수에서 빠져서 탄창으로 들어갈 탄약의 개수
*/
void AGun::Reload()
{
if (MaxAmmo == CurrentAmmo)
return;
UE_LOG(LogTemp,Warning, TEXT("RELOAD"));
int32 ReloadingAmmo = MaxAmmo - CurrentAmmo;
TotalAmmo -= ReloadingAmmo;
CurrentAmmo = MaxAmmo;
}
변수들은 모두 갖춰졌으므로, 먼저 이걸 화면 우측 하단에 뿌려주는 것부터 시작하였다.
탄약 개수 정보는 게임 전반에 걸쳐 보여줘야 하므로, 게임 전반에 쓰이는 UI 클래스에 포함시키는 것이 좋을 것 같다.
따라서 게임 전반에 쓰이는 KannaTPSOverlay 클래스를 만들고, 그 일부로 탄약 정보를 넣어줄 것이다.
먼저 UserWidget을 부모로하는 블루프린트 WBP_KannaTPSOverlay를 만들었다.
탄약 정보를 나타내는 UI를 대강 만들었다.
* 탄약 정보는 화면 우측 하단에 나타날 것이므로 추후 화면 비율의 가변성을 고려한다면 앵커를 우측 하단으로 설정해주어야 한다.
TotalAmmoText와 CurrentAmmoText가 있는데, 이 두 텍스트의 값은 C++ 코드로 넣어줄 것이다.
그러려면 이 블루프린트가 C++ 클래스를 상속받도록 해야한다.
UserWidget을 상속받는 클래스 KannaTPSOverlay를 만들고, 헤더 파일을 다음과 같이 만들어주었다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "KannaTPSOverlay.generated.h"
class UTextBlock;
UCLASS()
class KANNATPS_API UKannaTPSOverlay : public UUserWidget
{
GENERATED_BODY()
public:
void SetCurrentAmmoText(int32 amount);
void SetTotalAmmoText(int32 amount);
void HideAmmoText();
void ShowAmmoText();
private:
// meta = BindWidget은 블루프린트에서의 변수와 연동시키겠다는 의미이다.
UPROPERTY(meta = (BindWidget))
UTextBlock* CurrentAmmoText;
UPROPERTY(meta = (BindWidget))
UTextBlock* TotalAmmoText;
UPROPERTY(meta = (BindWidget))
UTextBlock* AmmoTextSlash;
};
위젯 블루프린트에서의 Text는 C++에서는 UTextBlock이다. 따라서 변수 타입도 UTextBlock 포인터로 해줘야한다.
이미 만들어져 있는 위젯 블루프린트와 연동시키는게 목적이므로, 변수들에 UPROPERTY(meta = (BindWidget))을 사용할 것이다.
이렇게 함으로써 블루프린트의 부모클래스를 이 C++클래스로 바꾸면 자동으로 프로퍼티들이 바인딩이 된다.
주의할 점은, 변수의 이름을 블루프린트와 C++의 것을 똑같이 일치시켜야한다.
그래야 바인딩이 제대로 된다.
게임에 사용할 오버레이가 만들어졌는데, 이것을 크로스헤어 때처럼 KannaCharacter의 BeginPlay에서 Add to Viewport를통해 표시해줄 수도 있지만, 게임 전반에 사용되는 것이므로 더 적절한 방법을 사용할 것이다.
그것은 HUD에 포함시키는 것이다.
프로젝트의 GameMode 블루프린트를 보면, HUD 기본 클래스를 설정할 수 있는 칸이 있다.
원래 기본값으로는 그냥 HUD클래스가 들어가있는데, 이미지는 새로 만든 것을 넣어준 버전이다.
새로운 HUD클래스를 사용하기 위해, 우선 C++에서 KannaTPSHUD 클래스를 새로 만들었다.
이 클래스의 멤버로써 방금 만든 KannaTPSOverlay를 사용할 수 있어야한다.
우선 헤더파일이다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "KannaTPSHUD.generated.h"
class UKannaTPSOverlay;
UCLASS()
class KANNATPS_API AKannaTPSHUD : public AHUD
{
GENERATED_BODY()
public:
FORCEINLINE UKannaTPSOverlay* GetKannaTPSOverlay() const {return KannaTPSOverlay;}
protected:
virtual void BeginPlay() override;
private:
UPROPERTY(EditDefaultsOnly)
TSubclassOf<UKannaTPSOverlay> KannaTPSOverlayClass;
UPROPERTY()
UKannaTPSOverlay* KannaTPSOverlay;
};
프라이빗 섹션의 TSubclassOf<UKannaTPSOverlay> KannaTPSOverlayClass; 에 주목해보자면,
우선 TSubClassOf는 말그대로 특정 타입의 서브클래스라는 의미이다.
그러므로 여기서 KannaTPSOverlayClass는 UKannaTPSOverlay의 서브클래스라면 무엇이든지 담을 수 있다.
그말인 즉슨, UKannaTPSOverlay를 상속받은 블루프린트도 여기에 넣어줄 수 있다.
사실 그것을 위해 해당 변수를 만든 것이고, 블루프린트 에디터 창에서 집어넣을 수 있도록 UPROPERTY(EditDefaultsOnly) 지정자를 사용한 것이다.
이제 이 C++파일을 상속받은 블루프린트 BP_KannaTPSHUD를 만들고나면, 다음과 같이 KannaTPSOverlayClass에 클래스를 집어넣을 수 있다. 여기에 아까 만든 BP_KannaTPSOverlay를 집어넣으면 된다.
이렇게 하여 KannaTPSHUD 클래스가 WBP_KannaTPSOverlay 클래스를 알 수 있게 되었다.
이제 KannaTPSHUD가 WBP_KannaTPSOverlay를 생성하고, 뷰포트에 추가할 수 있다.
이는 BeginPlay에서 수행할 것이다.
// Fill out your copyright notice in the Description page of Project Settings.
#include "HUD/KannaTPSHUD.h"
#include "HUD/KannaTPSOverlay.h"
void AKannaTPSHUD::BeginPlay()
{
Super::BeginPlay();
UWorld* World = GetWorld();
if (World)
{
APlayerController* Controller = World->GetFirstPlayerController();
if (Controller && KannaTPSOverlayClass)
{
KannaTPSOverlay = CreateWidget<UKannaTPSOverlay>(Controller, KannaTPSOverlayClass);
KannaTPSOverlay->AddToViewport();
}
}
}
CreateWidget 함수를 통해 위젯을 만들고, AddToViewport 함수를 통해 화면에 뿌려주면 된다.
CreateWidget 함수는 첫번째 인자로 APlayerController 포인터를 받는다. 이를 위해서는 World->GetFirstPlayerController()로 컨트롤러를 가져와서 써주면 된다.
싱글플레이 게임이므로 FirstPlayerController는 당연히 현재 플레이어의 컨트롤러일 것이기 때문이다.
게임모드의 HUD에 BP_KannaTPSHUD가 박혀있는 것을 한번 더 확인해주고, 게임을 실행하면 오버레이가 뜨게된다.
현재 진행을 좀 더 해둔 상태라 탄약 숫자가 쓰여져있는데, 원래 여기까지 했을 때는 0 / 0으로 뜨는 것이 맞다.
어쨌든 확실한 것은, 이제 KannaTPSHUD가 KannaTPSOverlay를 만들어서 화면에 뿌려준다는 것이다.
다음 포스팅에서는 실제로 UI에 탄약의 개수를 담는 과정을 다룰 것이다.
'언리얼 엔진 5 > 개발 일지' 카테고리의 다른 글
[UE5] 블루아카이브 TPS게임 개발일지 (40) - 장전 애니메이션 구현 1 (0) | 2024.01.14 |
---|---|
[UE5] 블루아카이브 TPS게임 개발일지 (39) - 탄약 UI 구현 2 (0) | 2024.01.14 |
[UE5] 블루아카이브 TPS게임 개발일지 (37) - 엄폐 시스템 구현 7 (0) | 2024.01.10 |
[UE5] 블루아카이브 TPS게임 개발일지 (36) - 엄폐 시스템 구현 6 (0) | 2024.01.10 |
[UE5] 블루아카이브 TPS게임 개발일지 (35) - 엄폐 시스템 구현 5 (0) | 2024.01.10 |