* 각 속생행은 각각의 태그를 가져야함
이제 우리는 this.AttributeTag에 설정해준 태그를 얻을수 있다
* TextButtonRowButton 리팩토링
* 모든속성을 방송하기
1. //아래코드에서 모든 속성에 대해 노가다 -> wtf
void UAttributeMenuWidgetController::BroadcastInitialValues()
{
UAuraAttributeSet* AS = CastChecked<UAuraAttributeSet>(AttributeSet); //부모인 위젯컨트롤러가 갖고있음
check(AttributeInfo) //DA가 set되었는지 확인
FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(FAuraGameplayTags::Get().Attributes_Primary_Strength); //일치태그 정보를 리턴
Info.AttributeValue=AS->GetStrength(); //속성정보 set 완료, value는 직접넣기로 설계함
AttributeInfoDelegate.Broadcast(Info); //set완료후 방송해야함
}
2. for loop로 돌리는게 좋겠다.
* 설계
1.
AS에서 FGameplayAttribute를 리턴해주는 델리게이트 생성
DECLARE_DELEGATE_RetVal(FGameplayAttribute, FAttributeSignature);
태그-속성을 매치해주는 Map 만듬
TMap<FGameplayTag,FAttributeSignature> TagsToAttributes;
생성자에서 맵에 추가
모든 태그에 대해
UAuraAttributeSet::UAuraAttributeSet()
{
const FAuraGameplayTags& GameplayTags = FAuraGameplayTags::Get(); //모든태그들 가져오기
FAttributeSignature StrengthDelegate;
StrengthDelegate.BindStatic(UAuraAttributeSet::GetStrengthAttribute); //델리게이트에 실제속성넣기(바인딩)
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,StrengthDelegate); //맵에추가<태그,속성>
FAttributeSignature IntDelegate;
IntDelegate.BindStatic(GetIntelligenceAttribute); //델리게이트에 실제속성넣기(바인딩)
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,IntDelegate); //맵에추가<태그,속성>
}
2.
리팩토링 완성
void UAttributeMenuWidgetController::BroadcastInitialValues()
{
UAuraAttributeSet* AS = CastChecked<UAuraAttributeSet>(AttributeSet); //부모인 위젯컨트롤러가 갖고있음
check(AttributeInfo) //DA가 set되었는지 확인
//기존
// FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(FAuraGameplayTags::Get().Attributes_Primary_Strength); //일치태그 정보를 리턴
// Info.AttributeValue=AS->GetStrength(); //속성정보 set 완료, value는 직접넣기로 설계함
// AttributeInfoDelegate.Broadcast(Info); //set완료후 방송해야함
//리팩토링
for(auto& Pair : AS->TagsToAttributes) //AS의 <태그,속성:델리게이트> 맵 순회
{
FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(Pair.Key) //태그에 맞는 속성 찾기
FGameplayAttribute Attr = Pair.Value.Execute(); //델리게이트내부의 FGameplayAttribute에 접근하려면 Signature.Execute()로 포장을 벗겨야함
Info.AttributeValue=Attr.GetNumericValue(AS); //GameplayAttribute의 껍질을까서 실제 값에 접근
//(Attr이 스태틱 함수에서 반환되기떄문에 -> 이속성이 연괸딘 AS가 누구인지 알려줘야함)
AttributeInfoDelegate.Broadcast(Info);
}
}
3. 문제 : 델리게이트 사용은 복잡, 코드가 늘어남
해결 : 함수포인터 사용
//FGameplayAttribute를 반환하는 함수포인터
TBaseStaticDelegateInstance<FGameplayAttribute(), FDefaultDelegateUserPolicy>::FFuncPtr FunctionPointer;
TMap<FGameplayTag,FAttributeSignature> TagsToAttributes; //기존
//함수포인터
TMap<FGameplayTag,TBaseStaticDelegateInstance<FGameplayAttribute(), FDefaultDelegateUserPolicy>::FFuncPtr> TagsToAttributes2;
FunctionPointer = GetStrengthAttribute; //바로 FGameplayAttribute 속성을 넣을수있다
- 기존코드
FunctionPointer = GetStrengthAttribute;
FAttributeSignature StrengthDelegate;
StrengthDelegate.BindStatic(UAuraAttributeSet::GetStrengthAttribute); //델리게이트에 실제속성넣기(바인딩)
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,StrengthDelegate); //맵에추가<태그,속성>
//리팩토링, 위젯메뉴컨트롤러
for(auto& Pair : AS->TagsToAttributes) //AS의 <태그,속성:델리게이트> 맵 순회
{
FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(Pair.Key); //태그에 맞는 속성 찾기
FGameplayAttribute Attr = Pair.Value.Execute(); //델리게이트내부의 FGameplayAttribute에 접근하려면 Signature.Execute()로 포장을 벗겨야함
Info.AttributeValue=Attr.GetNumericValue(AS); //GameplayAttribute의 껍질을까서 실제 값에 접근
//(Attr이 스태틱 함수에서 반환되기떄문에 -> 이속성이 연괸딘 AS가 누구인지 알려줘야함)
AttributeInfoDelegate.Broadcast(Info);
}
- 함수포인터 코드
:바인딩하는 부분이 없어도 된다!
: 바로 <태그, 속성>을 맵에 Add하면된다.
최종적으로 line3와 같이 줄일수있다.
FunctionPointer = GetStrengthAttribute;
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,FunctionPointer); //맵에추가<태그,속성>
//단축코드
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,GetStrengthAttribute); //맵에추가<태그,속성>
//리팩토링
for(auto& Pair : AS->TagsToAttributes) //AS의 <태그,속성:델리게이트> 맵 순회
{
FAuraAttributeInfo Info = AttributeInfo->FindAttributeInfoForTag(Pair.Key); //태그에 맞는 속성 찾기
FGameplayAttribute Attr = Pair.Value(); //FGameplayAttribute에 접근
Info.AttributeValue=Attr.GetNumericValue(AS); //GameplayAttribute의 껍질을까서 실제 값에 접근
//(Attr이 스태틱 함수에서 반환되기떄문에 -> 이속성이 연괸딘 AS가 누구인지 알려줘야함)
AttributeInfoDelegate.Broadcast(Info);
}
* 리팩토링 함수포인터
1. typedef로 줄일수있음
typedef TBaseStaticDelegateInstance<FGameplayAttribute(), FDefaultDelegateUserPolicy>::FFuncPtr FAttributeFuncPtr;
TMap<FGameplayTag,FAttributeFuncPtr> TagsToAttributes;
문제 : FGameAttribute 타입으로 제한됨
해결 : 템플릿
2. 템플릿
FGameplayAttribute를 T로 대체함
template<class T>
using TAttributeFuncPtr = typename TBaseStaticDelegateInstance<T, FDefaultDelegateUserPolicy>::FFuncPtr
선언시, 무슨타입인지 FuncPtr<반환타입(매개변수)>을 써주면됨
TMap<FGameplayTag,TAttributeFuncPtr<FGameplayAttribute()>> TagsToAttributes;
+ : FGameAttribute타입뿐아니라, 모든타입에 사용가능한 함수포인터임
3. 사용예시
Ptr<float반환 (매개변수들)>
* 맵에 모든 <태그, 속성> 추가 노가다
UAuraAttributeSet::UAuraAttributeSet()
{
const FAuraGameplayTags& GameplayTags = FAuraGameplayTags::Get(); //모든태그들 가져오기
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength,GetStrengthAttribute); //맵에추가<태그,속성>
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Intelligence,GetIntelligenceAttribute); //맵에추가<태그,속성>
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Resilience, GetResilienceAttribute);
TagsToAttributes.Add(GameplayTags.Attributes_Primary_Vigor, GetVigorAttribute);
}
* 결과
속성추가시, AS코드만 수정하면된다!
메뉴위젯 컨트롤러의 코드는 손댈필요 없음! (map을 단순히 순회하는 loop임)
* 정리
'UE5 > Attribute Menu' 카테고리의 다른 글
[UE5] Atttribute Menu 퀴즈 (0) | 2024.06.08 |
---|---|
[UE5] 속성변경시 위젯에 즉시반영 구현 (0) | 2024.06.08 |
[UE5] Attribute Info 델리게이트 // 위젯에 데이터 (속성명, 값) 연결하기 (0) | 2024.06.08 |
[UE5] 메뉴 위젯 컨트롤러 구현, BP내 사용가능한 위젯컨트롤러 게터 만들기, BP 상속안될때 해결방법, MVC 정리 (0) | 2024.06.08 |
[UE5] 속성정보 관련(구조체,탐색) 클래스구현, 속성입력 (0) | 2024.06.08 |