언리얼 엔진 5/개발 일지

[UE5] 블루아카이브 TPS게임 개발일지 (39) - 탄약 UI 구현 2

ciel45 2024. 1. 14. 10:28

KannaTPSOverlay의 탄약 개수가 실제로 업데이트되도록 할 것이다.

 

우선, KannaTPSOverlay 클래스 안에 탄약 개수를 설정하는 함수를 만들어주었다.

void UKannaTPSOverlay::SetCurrentAmmoText(int32 Amount)
{
	if (CurrentAmmoText)
	{
		FString String = FString::FromInt(Amount);
		CurrentAmmoText->SetText(FText::FromString(String));
	}
}

void UKannaTPSOverlay::SetTotalAmmoText(int32 Amount)
{
	if (TotalAmmoText)
	{
		FString String = FString::FromInt(Amount);
		TotalAmmoText->SetText(FText::FromString(String));
	}
}

인자로 int타입 숫자를 받아, FText로 변환하여 UI를 바꾼다.

 

 

 

그리고, 무기를 장착하고있지 않다면 굳이 탄약 개수 UI를 띄워줄 필요가 없을 것이다.

따라서 탄약 UI를 숨기고 보여주는 함수도 만들었다.

void UKannaTPSOverlay::HideAmmoText()
{
	CurrentAmmoText->SetVisibility(ESlateVisibility::Hidden);
	TotalAmmoText->SetVisibility(ESlateVisibility::Hidden);
	AmmoTextSlash->SetVisibility(ESlateVisibility::Hidden);
}

void UKannaTPSOverlay::ShowAmmoText()
{
	CurrentAmmoText->SetVisibility(ESlateVisibility::Visible);
	TotalAmmoText->SetVisibility(ESlateVisibility::Visible);
	AmmoTextSlash->SetVisibility(ESlateVisibility::Visible);
}

 

 

이제 이 함수들을 호출하여 UI를 업데이트 할 것이다.

업데이트 할 상황은 다음과 같다.

  • 총을 쏠 때 현재 탄약 개수 줄이기
  • 재장전할 때 현재 탄약 개수 늘리기, 전체 탄약 개수 줄이기
  • 총을 꺼낼 때 UI 보여주기, 집어넣을 때 UI 숨기기

총을 쏘고 재장전하는 것은 Gun의 역할이므로, Gun에서 KannaTPSOverlay를 참조할 수 있어야 한다.

HUD는 KannaCharacter가 사용하고 있는 것이라고 할 수 있다. 따라서 Gun에서 KannaCharacter를 통해, Overlay를 참조할 수 있게 하려고 한다.

 

Gun에서 KannaCharacter를 사용할 수 있도록, 변수를 하나 만들고 GetPlayerPawn을 통해 할당해주었다.

// Called when the game starts or when spawned
void AGun::BeginPlay()
{
	Super::BeginPlay();
	
	KannaCharacter = Cast<AKannaCharacter>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));

}

그렇다면 KannaCharacter에서는 KannaTPSOverlay를 넘겨줄 준비를 하고있어야 한다.

KannaCharacter에서도 KannaTPSOverlay 포인터 변수를 하나 만들고, 다음과 같이 할당해놓는다.

//BeginPlay에서 호출됨
void AKannaCharacter::InitKannaTpsOverlay()
{
	if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
	{
		AKannaTPSHUD* KannaTPSHUD = Cast<AKannaTPSHUD>(PlayerController->GetHUD());
		if (KannaTPSHUD)
		{
			KannaTPSOverlay = KannaTPSHUD->GetKannaTPSOverlay();
			if (KannaTPSOverlay)
			{
				KannaTPSOverlay->HideAmmoText(); //탄약 개수는 숨기는게 기본값
			}
		}
	}
}

플레이어 컨트롤러를 가져와 GetHUD로 KannaTPSHUD를 뽑아내고,  그 안에서 다시 KannaTPSOverlay 를 뽑아내어 변수에 저장해준다.

 

KannaTPSOverlay 포인터는 private 섹션에 있다. 넘겨주기 위한 간단한 public getter를 만들어주었다.

FORCEINLINE UKannaTPSOverlay* GetKannaTPSOverlay() {return KannaTPSOverlay;}

이제 Gun에서 KannaCharacter->GetKannaTPSOverlay()를 통하여 오버레이를 사용할 수 있다.

 

 

 

 

우선 Gun.cpp의 Fire 함수 맨 마지막에서 SetCurrentAmmoText를 호출하여 업데이트하도록 했다. 

void AGun::Fire(FVector& StartPoint, FVector& Direction)
{
	CurrentAmmo = FMath::Clamp(CurrentAmmo-1, 0, MaxAmmo);

	KannaCharacter->GetKannaTPSOverlay()->SetCurrentAmmoText(CurrentAmmo);
}

 

Reload에서도 다음과 같이 UI를 업데이트한다.

void AGun::Reload()
{
	if (MaxAmmo == CurrentAmmo)
		return;

	UE_LOG(LogTemp,Warning, TEXT("RELOAD"));

	int32 ReloadingAmmo = MaxAmmo - CurrentAmmo;

	TotalAmmo -= ReloadingAmmo;

	CurrentAmmo = MaxAmmo;

	KannaCharacter->GetKannaTPSOverlay()->SetCurrentAmmoText(CurrentAmmo);
	KannaCharacter->GetKannaTPSOverlay()->SetTotalAmmoText(TotalAmmo);
}

 

KannaCharacter에서는 무기를 넣고 뺌에 따라 UI를 보여주고 숨길 수 있도록, SwitchWeapon 함수를 다음과 같이 수정하였다.

void AKannaCharacter::SwitchWeapon()
{
	if(ActionState != EActionState::EAS_Neutral) return;

	if (CharacterState == ECharacterState::ECS_ArmedWithPistol) // 권총 -> 맨손
	{
		CharacterState = ECharacterState::ECS_Unarmed;
		CurrentWeapon = nullptr;
	}
	else if (CharacterState == ECharacterState::ECS_Unarmed) //맨손 -> 권총
	{
		CharacterState = ECharacterState::ECS_ArmedWithPistol;
		CurrentWeapon = WeaponList[0];
	}

	if(CurrentWeapon)
	{
		CurrentWeapon->SetOwner(this);
		CurrentWeapon->SetInstigator(this);
	}

	if (KannaTPSOverlay)
	{
		if (CurrentWeapon)
		{
			KannaTPSOverlay->ShowAmmoText();
			KannaTPSOverlay->SetTotalAmmoText(CurrentWeapon->GetTotalAmmo());
			KannaTPSOverlay->SetCurrentAmmoText(CurrentWeapon->GetCurrentAmmo());
		}
		else
		{
			KannaTPSOverlay->HideAmmoText();
		}
	}
}

KannaTPSOverlay가 null이 아니면,

  • CurrentWeapon이 null이 아니면 탄약 개수 보여주기
  • CurrentWeapon이 null, 즉 맨손이라면 탄약 UI 숨기기

 

이렇게 UI 시스템은 완성되었다.

 

 

참고로, Pistol의 탄약 변수의 기본 값은 다음과 같이 설정해주었다.

// Sets default values
APistol::APistol()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;

	FireMode = EFireMode::EFM_SEMIAUTO;

	Range = 10000.f;
	Damage = 35.f;

	MaxAmmo = 17;
}

// Called when the game starts or when spawned
void APistol::BeginPlay()
{
	Super::BeginPlay();
	
	if (KannaCharacter)
	{
		KannaCharacter->AddWeaponToList(this); //권총은 시작할 때부터 가지고 있어야 한다.

		this->AttachToComponent(KannaCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, FName("Pistol_Socket"));
	}

	TotalAmmo = 255;
	CurrentAmmo = 17;
}

 

탄창 용량이 17발로 권총 치고 좀 많은데, 실제로 칸나의 전용무기의 모델인 글록 17이 탄창에 17발이 들어간다고 한다.

 

 

 

총을 쏘고, 재장전함에 따라 탄약 개수가 잘 들어드는 것을 확인할 수 있었다.

 

이제 재장전 애니메이션을 넣어볼 것이다.