일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Unreal Engine
- dirty cow
- dtft
- ability task
- ret2libc
- 유니티
- gas
- frequency-domain spectrum analysis
- sampling theory
- DP
- linear difference equation
- CTF
- Rr
- 언리얼엔진
- 유스케이스
- 메카님
- DSP
- Double free
- stride
- 게임 개발
- MAC
- TSet
- AINCAA
- 게임개발
- 언리얼 엔진
- Security
- Race condition
- MLFQ
- 운영체제
- pdlc
- Today
- Total
다양한 기록
[Unreal GAS] Character Attribute Setting 본문
게임 데이터에 해당함
캐릭터에 설정할 어트리뷰트 목록
기본 어트리뷰트 | 최대값 어트리뷰트 |
체력 (Health) | 최대 체력 (MaxHealth) |
일반 공격 길이 (AttackRange) | 최대 일반 공격 길이 (MaxAttackRange) |
일반 공격 반경 (AttackRadius) | 최대 일반 공격 반경 (MaxAttackRadius) |
일반 공격력 (AttackRate) | 최대 공격력 (MaxAttackRate) |
어트리뷰트셋 생성
* 어트리뷰트 세트(Attribute Set)
- 단일 어트리뷰트 데이터인 GameplayAttributeData의 묶음
- GameplayAttributeData는 하나의 값이 아닌 두가지 값을 구성되어 있음
- BaseValue : 기본 값. 영구히 고정되는 고정 스텟값을 관리하는데 사용
- CurrentValue : 변동 값. 버프(Buff) 등으로 임시적으로 변동된 값을 관리하는데 사용
- 어트리뷰트 세트의 주요 함수
- PreAttributeChange : 어트리뷰트 변경 전에 호출 (변경해도 되는지)
- PostAttributeChange : 어트리뷰트 변경 후에 호출 (이러한 변화가 일어났다)
- PreGameplayEffectExecute : 게임플레이 이펙트 적용 전에 호출
- PostGameplayEffectExecute : 게임플레이 이펙트 적용 후에 호출
- 어트리뷰트 세트 접근자 매크로
- 많이 수행되는 기능에 대해 매크로를 만들어 제공
- ASC는 초기화될 때 같은 액터(OwnerActor)에 있는 UAttributeSet 타입 객체를 찾아서 등록
어트리뷰트 초기화나 접근하는데 귀찮으니까 매크로 있음
특정 속성에 대해 총 네개의 함수를 하나의 매크로로 지정
GAMEPLAYATTRIBUTE_PROPERTY_GETTER
- 어트리뷰트 세트나 어떤 어트리뷰트를 나타내는 클래스에 등록된 프로퍼티를 가져옴
GAMEPLAYATTRIBUTE_VALUE_GETTER
- CurrentValue 가져옴
GAMEPLAYATTRIBUTE_VALUE_SETTER
- BaseValue 설정
GAMEPLAYATTRIBUTE_VALUE_INITTER
- BaseValue와 CurrentValue 같은 값으로 설정해줌
예시 : AttackRange에 대해서
-> GetAttackRangeAttribute, GetAttackRange, SetAttackRange, InitAttackRange
Pre에서 두번째 인자가 레퍼런스인데 맘에 안들거나, 기획에서 벗어나면 다시 설정할 수 있도록 하기 위함
Post는 뭘 할 수는 없고 그냥 로그찍는 용도
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "ABCharacterAttributeSet.generated.h"
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
*
*/
UCLASS()
class ARENABATTLEGAS_API UABCharacterAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UABCharacterAttributeSet();
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, AttackRange);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, MaxAttackRange);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, AttackRadius);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, MaxAttackRadius);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, AttackRate);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, MaxAttackRate);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, Health);
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, MaxHealth);
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override;
protected:
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData AttackRange;
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData MaxAttackRange;
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData AttackRadius;
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData MaxAttackRadius;
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData AttackRate;
UPROPERTY(BlueprintReadOnly, Category = "Attack", meta = (AllowPrivateAccess = true))
FGameplayAttributeData MaxAttackRate;
UPROPERTY(BlueprintReadOnly, Category = "Health", meta = (AllowPrivateAccess = true))
FGameplayAttributeData Health;
UPROPERTY(BlueprintReadOnly, Category = "Health", meta = (AllowPrivateAccess = true))
FGameplayAttributeData MaxHealth;
};
어트리뷰트 셋 헤더
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attribute/ABCharacterAttributeSet.h"
UABCharacterAttributeSet::UABCharacterAttributeSet() :
AttackRange(100.0f),
MaxAttackRange(300.0f),
AttackRadius(50.0f),
MaxAttackRadius(150.0f),
AttackRate(30.0f),
MaxAttackRate(100.0f),
MaxHealth(100.0f)
{
InitHealth(GetMaxHealth());
}
void UABCharacterAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
}
void UABCharacterAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
}
NPC는 그냥 넣어주면 됨
플레이어는 ASC가 플레이어 스테이트에 있어서 어트리뷰트 셋도 같은 곳에 만들어야 함
UAbilitySystemComponent::InitializeComponent()에서
오너가 가지는 오브젝트들을 TArray에 일단 다 넣음
그리고 UAttributeSet 있으면 어트리뷰트 목록에 추가함
이래서 자동으로 ASC가 어트리뷰트 셋 찾는 것
AddUnique라 중복은 안되고, 다른 타입이면 가능
* NPC 태그가 비정상 작동?
디버그 모드에서 페이지 다운이나 페이지 업 하면 다른 애들도 볼 수 있음
NPC가 캐릭터가 공격하는데 자기까지 바뀌는 중
DefaultGame.ini에서 마지막 전역 설정 해주면 됨
타겟 액터에서 대미지가 하드코딩되어 있었는데 어트리뷰트 셋에서 읽어오도록 변경
UAbilitySystemBlueprintLibrary 쓰면 ASC 편하게 가져오기 가능
GetSet은 어트리뷰트 셋 가져오는 함수임
다음은 타겟에게 대미지 전달
void UABGA_AttackHitCheck::OnTraceResultCallback(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
if ( UAbilitySystemBlueprintLibrary::TargetDataHasHitResult(TargetDataHandle, 0) )
{
FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, 0);
ABGAS_LOG(LogABGAS, Log, TEXT("Target %s Detected"), *HitResult.GetActor()->GetName());
UAbilitySystemComponent* SourceASC = GetAbilitySystemComponentFromActorInfo_Checked();
UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(HitResult.GetActor());
if ( !SourceASC || !TargetASC )
{
ABGAS_LOG(LogABGAS, Error, TEXT("ASC Not Found.."));
return;
}
const UABCharacterAttributeSet* SourceAttribute = SourceASC->GetSet<UABCharacterAttributeSet>();
UABCharacterAttributeSet* TargetAttribute = const_cast<UABCharacterAttributeSet*>(TargetASC->GetSet<UABCharacterAttributeSet>());
if ( !SourceAttribute || !TargetAttribute )
{
ABGAS_LOG(LogABGAS, Error, TEXT("Attribute Not Found.."));
return;
}
const float AttackDamage = SourceAttribute->GetAttackRate();
TargetAttribute->SetHealth(TargetAttribute->GetHealth() - AttackDamage);
}
bool bReplicatedEndAbility = true;
bool bWasCancelled = false;
EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled);
}
소스랑 타겟 어트리뷰트 찾아서 계산
const_cast로 강제로 const 없애고 계산했는데, 이 방법보단 게임플레이 이펙트 사용하는 것이 좋음
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attribute/ABCharacterAttributeSet.h"
#include "ArenaBattleGAS.h"
UABCharacterAttributeSet::UABCharacterAttributeSet() :
AttackRange(100.0f),
MaxAttackRange(300.0f),
AttackRadius(50.0f),
MaxAttackRadius(150.0f),
AttackRate(30.0f),
MaxAttackRate(100.0f),
MaxHealth(100.0f)
{
InitHealth(GetMaxHealth());
}
void UABCharacterAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
if ( Attribute == GetHealthAttribute() )
{
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
}
}
void UABCharacterAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
if (Attribute == GetHealthAttribute())
{
ABGAS_LOG(LogABGAS, Log, TEXT("Health : %f -> %f"), OldValue, NewValue);
}
}
값이 의도한 범위를 벗어나지 않도록 설정 가능
Health 어트리뷰트 줄어드는데 0 미만으로 안 가는 걸 확인 가능
'언리얼 엔진 > Unreal Ability System' 카테고리의 다른 글
[Unreal GAS] Implementing Attack Hit Detect System (0) | 2025.01.13 |
---|---|
[Unreal GAS] Implementing Combo Action (0) | 2025.01.12 |
[Unreal GAS] Character Input Handling (0) | 2025.01.12 |
[Unreal GAS] 개요 (0) | 2025.01.11 |