인프런 [이득우의 언리얼 프로그래밍 Part4 - 게임플레이 어빌리티 시스템] 강의 공부 노트
강의를 들으며 개념 정리 후, 다른 프로젝트에 실습하고 있습니다.
1. MetaAttribute
Attribute 설정을 위해 사전에 설정하는 임시 Attribute
기획 추가에 유연한 대처 가능 → 데미지 기능에 대한 보정 기능들 처리
적용 후 바로 0으로 초기화하도록 설정
리플리케이션에서 제외하는 것이 일반적 (최종 변경 값만 전달하면 되기 때문)
1) AttributeSet에 MetaAttribute로 사용할 Damage Attribute 추가 후, 0으로 초기화
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attribute/VSCharacterAttributeSet.h"
#include "GameplayEffectExtension.h"
#include "ProjectLOL.h"
UVSCharacterAttributeSet::UVSCharacterAttributeSet()
:
AttackRange(100.f),
MaxAttackRange(300.f),
AttackRadius(50.f),
MaxAttackRadius(150.f),
AttackPower(30.f),
MaxAttackPower(100.f),
MaxHP(100.f),
Damage(0.f)
{
// Base HP, Current HP 모두 MaxHP로 초기화.
InitHP(GetMaxHP());
//LOL_LOG(LogProjectLOL, Log, TEXT("AttackRange : %f"), )
}
void UVSCharacterAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
//// HP가 0 이하로 내려가면 보정.
//if (Attribute == GetHPAttribute())
//{
// NewValue = FMath::Clamp(NewValue, 0, GetMaxHP());
//}
// Damage를 통해서 보정 값 설정하기.
if (Attribute == GetDamageAttribute())
{
NewValue = NewValue < 0.f ? 0.f : NewValue;
}
}
//void UVSCharacterAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
//{
// // HP 변경 값 디버깅.
// if (Attribute == GetHPAttribute())
// {
// LOL_LOG(LogProjectLOL, Log, TEXT("Changed HP %f -> %f"), OldValue, NewValue);
// }
//}
void UVSCharacterAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
float MinHP = 0.f;
if (Data.EvaluatedData.Attribute == GetHPAttribute())
{
LOL_LOG(LogProjectLOL, Warning, TEXT("Direct HP Access : %f"), GetHP());
SetHP(FMath::Clamp(GetHP(), MinHP, GetMaxHP()));
}
else if (Data.EvaluatedData.Attribute == GetDamageAttribute())
{
LOL_LOG(LogProjectLOL, Log, TEXT("Damage : %f"), GetDamage());
SetHP(FMath::Clamp(GetHP() - GetDamage(), MinHP, GetMaxHP()));
SetDamage(0.f);
}
}
2) GE를 DamageAttribute 기반으로 변경
결과 화면
2. 레벨에 따른 데미지 증가
레벨과 커브 테이블
GE에는 추가로 레벨 정보를 지정 가능
GE에 지정된 레벨 정보를 사용해 DataTable에서 특정 값을 가져오기 가능
ScalableFloat Modifier Type에서 사용 가능.
→ 활용하여 다양한 기능 구현 (현재 레벨에 따라 다른 초기 스탯 적용 ..)
CurveTable은 에디터로 제작
1) CurveTable 생성
선형 타입으로 생성
행 추가하기
롤 집중포화의 나무위키를 참고하여 적용해 보자!
레벨에 따른 HP 설정
레벨이 1부터 시작하니 최대 5 업그레이드인 6까지 0.1 배수씩 늘어나도록 설정하였다.
2) GE에 적용
CurveTable값을 배수로 설정하여 Multifly 계산으로 설정하였다.
3) CharacterPlayer에 GE와 Level 추가
UPROPERTY(EditAnywhere, Category = GAS)
TSubclassOf<class UGameplayEffect> InitStatEffect;
UPROPERTY(EditAnywhere, Category = GAS)
float Level;
4) GA에서 GE 생성하기
GE 생성과정
GameplayEffectContext
- GE에서 계산에 필요한 데이터를 담은 객체
- Instigator(가해자), Causer(가해 수단), HitResult(판정 정보)
GameplayEffectSpec
- Level, Modifier, Tag 등
- GameplayEffectContextHandle
ASC는 각 데이터를 Handle 객체를 통해 간접적으로 관리
GameplayEffectContextHandle 생성 후 GameplayEffectSpecHandle 생성
4-1) CharacterPlayer에서 GE 생성하기
void AVSCharacterChampionPlayer::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
// PlayerState에서 ASC 가져오기.
AVSPlayerState* VSPlayerState = GetPlayerState<AVSPlayerState>();
if (VSPlayerState)
{
ASC = VSPlayerState->GetAbilitySystemComponent();
//...
// GE 생성.
FGameplayEffectContextHandle EffectContextHandle = ASC->MakeEffectContext();
EffectContextHandle.AddSourceObject(this);
FGameplayEffectSpecHandle EffectSpecHandle = ASC->MakeOutgoingSpec(InitStatEffect, Level, EffectContextHandle);
if (EffectSpecHandle.IsValid())
{
ASC->BP_ApplyGameplayEffectSpecToSelf(EffectSpecHandle);
}
}
}
4-2) CharacterPlayer의 Blueprint에서 GE 지정
결과 화면
1, 3, 6 Level HP 변경된 값
이제 이 Level도 시스템 상 데이터로 변경해 주는 작업을 해야 할 듯하다.
'UnrealEngine5 > 공부' 카테고리의 다른 글
[UE5/GAS] 데미지 전달에 GE 활용하기 (1) (0) | 2025.06.02 |
---|---|
[UE5/GAS] Character Attribute로 Damage 전달하기 (0) | 2025.06.01 |
[UE5/GAS] AnimNotify와 Trigger Tag로 공격 판정하기 (0) | 2025.05.30 |
[UE5/GAS] 상태Tag와 AT를 활용한 GA, AT 규칙 (0) | 2025.05.29 |
[UE5/GAS] GAS와 CharacterPlayer, GA와 AbilityTask (0) | 2025.05.28 |