1. 보유한 어빌리티 순회하여 업그레이드 태그 전송
플레이어 캐릭터가 보유한(Activated) 어빌리티를 대상으로 순회를 하고, 랜덤한 어빌리티를 뽑아 해당 어빌리티의 랜덤 업그레이드 태그를 전송한다.
(1) AuraPlayerState - 델리게이트 선언
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnRandomUpgradeTagsGenerated, AAuraPlayerState*, AuraPlayerState, TArray<FGameplayTag>&, RandomUpgradeTags);
// 랜덤 업그레이드 선택 델리게이트
FOnRandomUpgradeTagsGenerated OnRandomUpgradeTagsGeneratedDelegate;
플레이어 스테이트에서 선택한 세 개의 업그레이드 태그를 게임 모드로 전달하는 델리게이트를 선언한다.
(2) 보유한 어빌리티 태그 가져오기
// 활성화 모든 어빌리티의 태그를 반환
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GAS|Abilities")
TArray<FGameplayTag> GetAllActiveAbilityTags() const;
TArray<FGameplayTag> AAuraPlayerState::GetAllActiveAbilityTags() const
{
TArray<FGameplayTag> AllActiveTags;
// 활성화된 어빌리티
TArray<FGameplayAbilitySpec> ActiveSpecs = AbilitySystemComponent->GetActivatableAbilities();
for (FGameplayAbilitySpec& Spec : ActiveSpecs)
{
FGameplayTagContainer AbilityTagContainer = Spec.Ability->AbilityTags;
if (AbilityTagContainer.HasTag(FAuraGameplayTags::Get().Abilities_None))
continue;
for (auto Tag : AbilityTagContainer)
{
if (Tag.MatchesTag(FGameplayTag::RequestGameplayTag(TEXT("Abilities"))))
{
// 어빌리티 태그라면 추가
AllActiveTags.Add(Tag);
}
}
}
return AllActiveTags;
}
ASC의 활성화 된 어빌리티를 가져온 이후, 부모 태그가 Abilities에 해당하는 모든 어빌리티 태그를 배열로 내보낸다.
(3) 세 개의 랜덤 태그를 뽑아 전달하는 함수
TArray<FGameplayTag> AAuraPlayerState::GetRandomUpgradeTagsForActivatedAbility_Three()
{
const TArray<FGameplayTag> ActivatedAbilityTags = GetAllActiveAbilityTags();
TArray<FGameplayTag> RandomUpgradeTags;
RandomUpgradeTags.Empty();
// 주어진 어빌리티 태그에 대해 랜덤한 업그레이드 태그 뽑기
if (UAbilityUpgradeInfo* Info = UAuraAbilitySystemLibrary::GetAbilityUpgradeInfo(this))
{
int ActivatedAbilityTagsNum = ActivatedAbilityTags.Num();
int RandValue0 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
int RandValue1 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
int RandValue2 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
// 랜덤으로 뽑은 어빌리티 태그는 중복 가능 -> 파이어볼트 업그레이드 2개 노출 가능
const auto Tag0 = ActivatedAbilityTags[RandValue0];
const auto Tag1 = ActivatedAbilityTags[RandValue1];
const auto Tag2 = ActivatedAbilityTags[RandValue2];
FGameplayTag UpgradeTag0;
FGameplayTag UpgradeTag1;
FGameplayTag UpgradeTag2;
// 루프 함수 제한
int CurrentAttempt = 0;
// 동일한 태그가 없을 때까지 뽑기
while (UpgradeTag0 == UpgradeTag1 || UpgradeTag1 == UpgradeTag2 || UpgradeTag0 == UpgradeTag2)
{
UpgradeTag0 = Info->GetRandomUpgradeTagForAbility(Tag0);
UpgradeTag1 = Info->GetRandomUpgradeTagForAbility(Tag1);
UpgradeTag2 = Info->GetRandomUpgradeTagForAbility(Tag2);
CurrentAttempt++;
if (CurrentAttempt > 10)
break;
}
RandomUpgradeTags.Add(UpgradeTag0);
RandomUpgradeTags.Add(UpgradeTag1);
RandomUpgradeTags.Add(UpgradeTag2);
// AuraGameModeBase에서 바인딩
OnRandomUpgradeTagsGeneratedDelegate.Broadcast(this, RandomUpgradeTags);
}
return RandomUpgradeTags;
}
(3-1) 활성화 된 어빌리티 중 랜덤으로 세 개의 어빌리티 추출
const TArray<FGameplayTag> ActivatedAbilityTags = GetAllActiveAbilityTags();
TArray<FGameplayTag> RandomUpgradeTags;
RandomUpgradeTags.Empty();
// 주어진 어빌리티 태그에 대해 랜덤한 업그레이드 태그 뽑기
if (UAbilityUpgradeInfo* Info = UAuraAbilitySystemLibrary::GetAbilityUpgradeInfo(this))
{
int ActivatedAbilityTagsNum = ActivatedAbilityTags.Num();
int RandValue0 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
int RandValue1 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
int RandValue2 = UKismetMathLibrary::RandomIntegerInRange(0, ActivatedAbilityTagsNum-1);
// 랜덤으로 뽑은 어빌리티 태그는 중복 가능 -> 파이어볼트 업그레이드 2개 노출 가능
const auto Tag0 = ActivatedAbilityTags[RandValue0];
const auto Tag1 = ActivatedAbilityTags[RandValue1];
const auto Tag2 = ActivatedAbilityTags[RandValue2];
랜덤한 인티저 세 개를 이용해 배열에 직접 접근하여 3개의 어빌리티 태그를 추출한다.
(3-2) 추출한 어빌리티 태그로부터 랜덤한 업그레이드 태그 추출
FGameplayTag UpgradeTag0;
FGameplayTag UpgradeTag1;
FGameplayTag UpgradeTag2;
// 루프 함수 제한
int CurrentAttempt = 0;
// 동일한 태그가 없을 때까지 뽑기
while (UpgradeTag0 == UpgradeTag1 || UpgradeTag1 == UpgradeTag2 || UpgradeTag0 == UpgradeTag2)
{
UpgradeTag0 = Info->GetRandomUpgradeTagForAbility(Tag0);
UpgradeTag1 = Info->GetRandomUpgradeTagForAbility(Tag1);
UpgradeTag2 = Info->GetRandomUpgradeTagForAbility(Tag2);
CurrentAttempt++;
if (CurrentAttempt > 10)
break;
}
RandomUpgradeTags.Add(UpgradeTag0);
RandomUpgradeTags.Add(UpgradeTag1);
RandomUpgradeTags.Add(UpgradeTag2);
Info는 업그레이드 정보를 저장하고 있다. 해당 클래스의 함수를 사용하여 주어진 어빌리티 태그에 해당하는 업그레이드를 랜덤하게 추출한다.
(3-2-1) AbilityUpgradeInfo 클래스의 GetRandomUpgradeTagForAbility 함수
FGameplayTag UAbilityUpgradeInfo::GetRandomUpgradeTagForAbility(const FGameplayTag& AbilityTag)
{
auto AuraTags = FAuraGameplayTags::Get();
FAuraAbilityUpgradeInfoArray UpgradeInfoArray = GetUpgradesForAbility(AbilityTag);
if (UpgradeInfoArray.UpgradeInfos.IsEmpty())
return AuraTags.Abilities_None;
int32 ArrayNum = UpgradeInfoArray.UpgradeInfos.Num();
int32 RandValue = UKismetMathLibrary::RandomIntegerInRange(0, ArrayNum - 1);
return UpgradeInfoArray.UpgradeInfos[RandValue].UpgradeEffectTag;
}
업그레이드 정보 배열에서 어빌리티 태그를 이용해 사용 가능한 모든 업그레이드를 추출하여 랜덤한 태그를 내보내는 함수이다.
(3-3) 델리게이트 호출
// AuraGameModeBase에서 바인딩
OnRandomUpgradeTagsGeneratedDelegate.Broadcast(this, RandomUpgradeTags);
}
return RandomUpgradeTags;
}
AuraGameModeBase에서 바인딩하는 델리게이트를 호출하여 세 개의 태그를 전달한다.
(4) 델리게이트 바인딩
void AAuraGameModeBase::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
if (NewPlayer)
{
if (AAuraHUD* AuraHUD = Cast<AAuraHUD>(NewPlayer->GetHUD()))
{
// 어빌리티 업그레이드 카드 세팅
AuraHUD->OnInitializeGameModeDelegate.Broadcast();
if (AAuraPlayerState* AuraPS = NewPlayer->GetPlayerState<AAuraPlayerState>())
{
AuraPS->OnRandomUpgradeTagsGeneratedDelegate.AddDynamic(this, &AAuraGameModeBase::HandleRandomUpgradeTagsGenerated);
AuraPS->OnPlayerStateInitialized.AddDynamic(this, &AAuraGameModeBase::HandlePlayerStateInitialized);
}
}
}
}
(4-1) 콜백 함수
void AAuraGameModeBase::HandleRandomUpgradeTagsGenerated(AAuraPlayerState* AuraPS,
TArray<FGameplayTag>& RandomUpgradeTags)
{
if (!HasAuthority())
return;
if (RandomUpgradeTags.IsEmpty() || RandomUpgradeTags.Num() < 3)
return;
if (AAuraHUD* AuraHUD = Cast<AAuraHUD>(AuraPS->GetPlayerController()->GetHUD()))
{
auto Tag0 = RandomUpgradeTags[0];
auto Tag1 = RandomUpgradeTags[1];
auto Tag2 = RandomUpgradeTags[2];
AuraHUD->ReceivedCardsDelegate.Broadcast(Tag0, Tag1, Tag2);
}
}
전달 받은 태그를 AuraHUD로 전달하여 카드에 반영한다.
AuraHUD에서는 아래 콜백 함수가 호출된다.
void AAuraHUD::HandleRandomAbilityUpgrade(FGameplayTag UpgradeTag0, FGameplayTag UpgradeTag1,
FGameplayTag UpgradeTag2)
{
auto* Info = UAuraAbilitySystemLibrary::GetAbilityUpgradeInfo(this);
if (Info == nullptr)
return;
auto* CardViewModel_0 = CardSelectionViewModel->GetCardViewModelByIndex(0);
if (CardViewModel_0)
{
auto Upgrade = Info->GetUpgradeInfoForUpgradeTag(UpgradeTag0);
CardViewModel_0->SetUpgradeTag(Upgrade.UpgradeEffectTag);
CardViewModel_0->SetUpgradeDescription(Upgrade.UpgradeDescription);
CardViewModel_0->SetUpgradeName(Upgrade.UpgradeName);
CardViewModel_0->SetUpgradeMaxLevel(Upgrade.UpgradeMaxLevel);
CardViewModel_0->OnUpgradeTagAssignedDelegate.Broadcast(UpgradeTag0);
}
auto* CardViewModel_1 = CardSelectionViewModel->GetCardViewModelByIndex(1);
if (CardViewModel_1)
{
auto Upgrade = Info->GetUpgradeInfoForUpgradeTag(UpgradeTag1);
CardViewModel_1->SetUpgradeTag(Upgrade.UpgradeEffectTag);
CardViewModel_1->SetUpgradeDescription(Upgrade.UpgradeDescription);
CardViewModel_1->SetUpgradeName(Upgrade.UpgradeName);
CardViewModel_1->SetUpgradeMaxLevel(Upgrade.UpgradeMaxLevel);
CardViewModel_1->OnUpgradeTagAssignedDelegate.Broadcast(UpgradeTag1);
}
auto* CardViewModel_2 = CardSelectionViewModel->GetCardViewModelByIndex(2);
if (CardViewModel_2)
{
auto Upgrade = Info->GetUpgradeInfoForUpgradeTag(UpgradeTag2);
CardViewModel_2->SetUpgradeTag(Upgrade.UpgradeEffectTag);
CardViewModel_2->SetUpgradeDescription(Upgrade.UpgradeDescription);
CardViewModel_2->SetUpgradeName(Upgrade.UpgradeName);
CardViewModel_2->SetUpgradeMaxLevel(Upgrade.UpgradeMaxLevel);
CardViewModel_2->OnUpgradeTagAssignedDelegate.Broadcast(UpgradeTag2);
}
}
각 카드의 뷰 모델의 필드 노티파이를 변경하고 태그 할당 완료 델리게이트를 호출한다.

각 카드의 뷰 모델에 태그 할당이 완료되면 배경 색을 바꾸는 함수를 호출한다.
2. 어빌리티 종류에 따른 카드 배경 색 변화시키기

전달받은 태그를 Matches Tag 함수로 분별하여 배경 색의 틴트를 변경한다.

'UE 5 스터디 > Gameplay Ability System(GAS)' 카테고리의 다른 글
| 32-10. 로그 라이크 - (5) 저장 - 어빌리티 업그레이드 저장 및 불러오기 (0) | 2025.06.17 |
|---|---|
| 32-9. 로그 라이크 - (4) 체크 포인트 액터 - 클릭하면 업그레이드 카드 선택 UI를 노출하는 액터 생성하기 (0) | 2025.06.16 |
| 32-7. 로그 라이크 - (3) 게임플레이 어빌리티 - (3) PlayerState에서 업그레이드 태그 관리 (0) | 2025.06.10 |
| 32-6. 로그 라이크 - (2) MVVM - (3) 뷰에 뷰 모델 바인딩 이후에 특정 함수 호출하기 (0) | 2025.06.09 |
| 32-5. 로그 라이크 - (3) 게임플레이 어빌리티 - (1) 어빌리티 재구조화 및 업그레이드 기능 적용 (1) | 2025.06.09 |
