Unreal GAS (19) - DataAsset, AbilitySystem Blueprint Library

wnsduf0000·2025년 12월 1일

Unreal_GAS

목록 보기
20/34
  • Attribute Data Asset
    • Attribute의 GameplayTag와 함께 Attribute의 이름, 부가 설명, 값을 담는 구조체 FAuraAttributeInfo를 배열로 갖는 DataAsset을 생성하여, 게임 내에서 Attribute 및 그와 관련된 정보에 쉽게 접근할 수 있게 하려고 함.

    • AttributeDataAsset은 AttributeMenuWidgetController가 소유하여, 플레이어가 Attribute Menu 위젯을 보려고 할 때 사용할 목적으로 만드는 것임.
      (태그 자체는 AuraGameplayTags의 FAuraGameplayTags에 추가하지만, 해당 태그에 대한 정보는 에디터에서 AttributeInfo DataAsset를 생성하고 그 곳에 추가하여 접근하는 방식임)

      #include "CoreMinimal.h"
      #include "Engine/DataAsset.h"
      #include "GameplayTagContainer.h"
      #include "AttributeInfo.generated.h"
      
      USTRUCT(BlueprintType)
      struct FAuraAttributeInfo
      {
      	GENERATED_BODY()
      
      public:
      	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
      	FGameplayTag AttributeTag = FGameplayTag();
      
      	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
      	FText AttributeName = FText();
      
      	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
      	FText AttributeDescription = FText();
      
      	// 실제 값은 DataAsset에서 설정하는 것이 아니라 AttributeSet에 존재할 것이므로
      	// BlueprintReadOnly로 설정하고, 
      	UPROPERTY(BlueprintReadOnly)
      	float AttributeValue = 0.f;
      };
      
      
      UCLASS()
      class AURA_API UAttributeInfo : public UDataAsset
      {
      	GENERATED_BODY()
      	
      public:
      	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
      	TArray<FAuraAttributeInfo> AttributeInformation;
      
      	FAuraAttributeInfo FindAttributeInfoForTag(const FGameplayTag& AttributeTag, bool bLogNotFound = false) const;
      };
      
      #include "AbilitySystem/Data/AttributeInfo.h"
      
      FAuraAttributeInfo UAttributeInfo::FindAttributeInfoForTag(const FGameplayTag& AttributeTag, bool bLogNotFound) const
      {
        for (const FAuraAttributeInfo& Info : AttributeInformation)
        {
      	  if (Info.AttributeTag.MatchesTagExact(AttributeTag))
          {
              return Info;
          }
      	}
      
       if (bLogNotFound)
       {
          UE_LOG(LogTemp, Error, TEXT("Attribute %s not Found on AttributeInfo %s"), *AttributeTag.ToString(), *GetNameSafe(this));
       }
      
      	return FAuraAttributeInfo();
      }
    • FindAttributeInfoForTag()로 DataAsset의 AttributeInformation 배열에 존재하는 GameplayTag 중 일치하는 것을 가져올 수 있음.

  • Attribute Widget Controller
    #include "CoreMinimal.h"
    #include "UI/WidgetController/AuraWidgetController.h"
    #include "AttributeMenuWidgetController.generated.h"
    
    struct FAuraAttributeInfo;
    class UAttributeInfo;
    
    // FAuraAttributeInfo를 전파할 델리게이트 FAttributeInfoSignature 선언
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAttributeInfoSignature, const FAuraAttributeInfo&, Info);
    
    
    UCLASS(BlueprintType, Blueprintable)
    class AURA_API UAttributeMenuWidgetController : public UAuraWidgetController
    {
    	GENERATED_BODY()
    	
    public:
    	virtual void BroadcastInitialValues() override;
    
    	virtual void BindCallbacksToDependencies() override;
    
    	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
    	FAttributeInfoSignature AttributeInfoDelegate;
    	
    protected:
    	// UAttributeInfo를 선언하고, 이를 에디터의 블루프린트에서 설정함.
    	UPROPERTY(EditDefaultsOnly)
    	TObjectPtr<UAttributeInfo> AttributeInfo;
    };
    • UOverlayWidgetController와 마찬가지로, WBP_AttributeMenu와 실제 참조할 데이터들 사이를 중재할 UAttributeMenuWidgetController를 생성함.

    • AttributeInfo DataAsset을 지니며, 이 정보를 FAttributeInfoSignature 델리게이트를 통해 전파함.

      #include "UI/WidgetController/AttributeMenuWidgetController.h"
      #include "AbilitySystem/AuraAttributeSet.h"
      #include "AbilitySystem/Data/AttributeInfo.h"
      #include "AuraGameplayTags.h"
      
      void UAttributeMenuWidgetController::BroadcastInitialValues()
      {
      	UAuraAttributeSet* AS = CastChecked<UAuraAttributeSet>(AttributeSet);
      	
      	check(AttributeInfo);
      	
      	FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(FAuraGameplayTags::Get().Attributes_Primary_Strength, true);
      	Info.AttributeValue = AS->GetStrength();
      
      	AttributeInfoDelegate.Broadcast(Info);
      }
      
      void UAttributeMenuWidgetController::BindCallbacksToDependencies()
      {
      
      }
    • AttributeInfo DataAsset에서 Attribute에 해당하는 실제 값을 AttributeSet에서 가져와서 설정해주어야 하므로, UAuraAttributeSet에 접근하여 FAuraGameplayTag의 GameplayTag 변수를 이용하여 AttributeInfo의 레퍼런스를 얻고, 거기에 AttributeValue만 따로 설정함.
      (이미 AttributeName, AttributeTag, AttributeDescription은 에디터 상에서 다 설정했으므로)
      AttributeValue까지 설정한 FAuraAttributeInfo를 델리게이트로 발송함.

    • AuraWidgetController의 변경 사항

      • BroadcastInitialValues를 BlueprintCallable로 수정함.
        (AttributeMenu의 경우 AttributeMenu가 생성되는 시점에서 AttributeSet에 있는 실제 Attribute의 값을 업데이트해야 하기 때문임)
  • Ability System Blueprint Library
    • UAuraAbilitySystemLibrary 블루프린트 라이브러리 클래스를 생성
      • WBP_Overlay, 즉 HUD용 위젯 같은 경우, 게임 중 계속해서 화면에 존재하는 위젯이므로, 플레이어 캐릭터인 Aura(AuraPlayerChraracter)가 플레이어 컨트롤러에 의해 Possessed 되거나 PlayerState가 Replicate 될 때 호출되는 InitAbilityActorInfo()에서 AuraHUD의 InitOverlay()를 호출하면서 OverlayWidgetController를 지정해주는 과정을 거침.

      • 하지만, AttributeMenu의 경우 항상 게임 내에 존재하지도 않고, 게임이 시작되자마자 초기화 되는 것이 아닌, 플레이어가 버튼을 클릭하여 WBP_AttributeMenu가 화면에 출력될 때 AttributeMenuWidgetController를 지정하도록 하는 것이 효율적임.
        따라서 WBP_AttributeMenu에서 직접 AttributeMenuWidgetController를 지정할 수 있도록 WidgetController의 레퍼런스를 얻어올 수 있는 블루프린트 호출 가능 함수를 만들되, 이를 AttributeMenu에서 직접 정의하지는 않도록 하는 것이 목적임.

        • PlayerController를 통해 HUD에 접근 가능하고, 현재 HUD 클래스는 AuraHUD로 설정해두었으므로 AuraHUD로 캐스팅하여 WidgetController들에 접근 가능함.
        • PlayerState 또한 PlayerController를 통해 접근 가능하고, PlayerState를 통해서 AbilitySystemComponent에 접근할 수 있으며, AbilitySystemComponent에서 AttributeSet으로 접근 가능함.
        #include "CoreMinimal.h"
        #include "Kismet/BlueprintFunctionLibrary.h"
        #include "UI/WidgetController/OverlayWidgetController.h"
        #include "AuraAbilitySystemLibrary.generated.h"
        
        UCLASS()
        class AURA_API UAuraAbilitySystemLibrary : public UBlueprintFunctionLibrary
        {
        	GENERATED_BODY()
        	
        public:
        	UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|WidgetController")
        	static UOverlayWidgetController* GetOverlayWidgetController(const UObject* WorldContextObject);
        
        	UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|WidgetController")
        	static UAttributeMenuWidgetController* GetAttributeMenuWidgetController(const UObject* WorldContextObject);
        };
        #include "AbilitySystem/AuraAbilitySystemLibrary.h"
        #include "Kismet/GameplayStatics.h"
        #include "Player/AuraPlayerState.h"
        #include "UI/HUD/AuraHUD.h"
        #include "UI/WidgetController/AuraWidgetController.h"
        
        UOverlayWidgetController* UAuraAbilitySystemLibrary::GetOverlayWidgetController(const UObject* WorldContextObject)
        {
        	if (APlayerController* PC = UGameplayStatics::GetPlayerController(WorldContextObject, 0))
        	{
        		if (AAuraHUD* AuraHUD = Cast<AAuraHUD>(PC->GetHUD()))
        		{
        			AAuraPlayerState* PS = PC->GetPlayerState<AAuraPlayerState>();
        			UAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent();
        			UAttributeSet* AS = PS->GetAttributeSet();
        
        			const FWidgetControllerParams WidgetControllerParams(PC, PS, ASC, AS);
        
        			return AuraHUD->GetOverlayWidgetController(WidgetControllerParams);
        		}
        	}
        
            return nullptr;
        }
        
        UAttributeMenuWidgetController* UAuraAbilitySystemLibrary::GetAttributeMenuWidgetController(const UObject* WorldContextObject)
        {
        	if (APlayerController* PC = UGameplayStatics::GetPlayerController(WorldContextObject, 0))
        	{
        		if (AAuraHUD* AuraHUD = Cast<AAuraHUD>(PC->GetHUD()))
        		{
        			AAuraPlayerState* PS = PC->GetPlayerState<AAuraPlayerState>();
        			UAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent();
        			UAttributeSet* AS = PS->GetAttributeSet();
        
        			const FWidgetControllerParams WidgetControllerParams(PC, PS, ASC, AS);
        
        			return AuraHUD->GetAttributeMenuWidgetController(WidgetControllerParams);
        		}
        	}
        
        	return nullptr;
        }
        
profile
저는 게임 개발자로 일하고 싶어요

0개의 댓글