본문 바로가기
Unreal 게임 개발/Unreal 강의 개인 정리

스킬 구현 (Cost & CoolTime / 최종 데미지 수동 계산) - GAS

by daisy0461 2025. 8. 28.

스킬에 사용에 필요한 Cost를 구현해보자.

간단하게 GameplayEffect를 제작한다.

이때 Duration Policy는 Instant로 해야한다.

이 Blueprint의 의미는 SkillEnergy값에서 -40을 뺀다는 의미이다.

현재 SkillEnergy가 100이면 2번은 가능하지만 3번은 불가능하게 제작하려고 하는 것이다.

Skill GA에 다음과 같이 제작한 Blueprint를 지정을 해주면 알아서 처리해준다.

 

이제 쿨타임 Effect Blueprint는 다음과 같이 제작한다.

이렇게만 하면 Ability는 발동만하고 추가적인 처리를 해주지 않는다.

그렇기에 Tag를 추가하고

쿨타임 Effect의 해당 부분을 추가해준다.

남은 시간 같은 것은 API로 지원해주지만 자동으로 CoolTime으로 막아주지 않아서 

Activation Blocked Tags에 추가해준다.

 


이제 데미지를 범위에 따라 다르게 만들어보자.

위 Class를 상속받아주고 아래와 같이 작성한다.

#include "GE/ABSkillDamageExecCalc.h"
#include "AbilitySystemComponent.h"
#include "Attribute/ABCharacterSkillAttributeSet.h"
#include "Attribute/ABCharacterAttributeSet.h"

void UABSkillDamageExecCalc::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
	//이펙트를 발동시키는 정보에 대해서 ExecutionParams 파라미터에 들어온다. (웬만하면 모든 정보가 다 들어가있다.)
	//바꿀 어트리뷰트 값들에 대해서는 OutExecutionOutput에 최종 데이터를 추가해주면 된다.

	Super::Execute_Implementation(ExecutionParams, OutExecutionOutput);

	UAbilitySystemComponent* SourceASC = ExecutionParams.GetSourceAbilitySystemComponent();
	UAbilitySystemComponent* TargetASC = ExecutionParams.GetTargetAbilitySystemComponent();

	if (!SourceASC || !TargetASC) return;
	
	AActor* SourceActor = SourceASC->GetAvatarActor();
	AActor* TargetActor = TargetASC->GetAvatarActor();

	if (!SourceActor || !TargetActor) return;

	const float MaxDamageRange = SourceASC->GetNumericAttributeBase(UABCharacterSkillAttributeSet::GetSkillRangeAttribute());
	const float MaxDamage = SourceASC->GetNumericAttributeBase(UABCharacterSkillAttributeSet::GetSkillAttackRateAttribute());
	//아래처럼만 작성하면 거리가 최대일 때 최대 데미지가 들어간다.
	const float Distance = FMath::Clamp(SourceActor->GetDistanceTo(TargetActor), 0.0f, MaxDamageRange);
	//그렇기에 Inverse시켜준다.
	const float InvDamageRatio = 1.0f - Distance / MaxDamageRange;
	float Damage = InvDamageRatio * MaxDamage;

	//데미지를 전달하는 것이기 때문에 GetDamageAttribute라는 속성으로 전달하고 Additive 연산을 사용하며 넘기는 값은 Damage라는 의미이다.
	OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UABCharacterAttributeSet::GetDamageAttribute(), EGameplayModOp::Additive, Damage));
}

이제 적용하는 작업이 남았다.

SkillDamage를 입히는 Effect에 Executions에 요소를 추가하여 방금 제작한 Class를 넣어주면 된다.

 

멀수록 데미지가 줄어드는 것을 확인할 수 있다.