PART 4 - 강의 4/4
차징/채널링 어빌리티
버튼 홀드와 시간 기반 어빌리티
01
InputReleased 오버라이드
버튼 릴리즈 감지
차징 어빌리티 기본 구조
UCLASS()
class UGA_ChargedShot : public UGameplayAbility
{
GENERATED_BODY()
public:
UGA_ChargedShot();
protected:
virtual void ActivateAbility(...) override;
// 버튼 릴리즈 시 호출
virtual void InputReleased(
const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo) override;
UFUNCTION()
void OnChargeComplete(float ChargeTime);
protected:
UPROPERTY(EditDefaultsOnly)
float MaxChargeTime = 2.0f;
UPROPERTY(EditDefaultsOnly)
float MinDamageMultiplier = 1.0f;
UPROPERTY(EditDefaultsOnly)
float MaxDamageMultiplier = 3.0f;
private:
UPROPERTY()
UAbilityTask_WaitForCharge* ChargeTask;
};
02
차징 구현
시간에 따른 데미지 증가
차징 어빌리티 구현
void UGA_ChargedShot::ActivateAbility(...)
{
if (!CommitAbility(...)) { EndAbility(...); return; }
// 차지 몽타주 재생
if (ChargeMontage)
{
UAbilityTask_PlayMontageAndWait* MontageTask =
UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this, NAME_None, ChargeMontage);
MontageTask->ReadyForActivation();
}
// 차지 Task 시작
ChargeTask = UAbilityTask_WaitForCharge::CreateTask(
this, MaxChargeTime);
ChargeTask->OnChargeComplete.AddDynamic(
this, &UGA_ChargedShot::OnChargeComplete);
ChargeTask->ReadyForActivation();
// 차지 시작 GameplayCue
FGameplayCueParameters CueParams;
CueParams.Location = GetAvatarActorFromActorInfo()->GetActorLocation();
K2_ExecuteGameplayCue(
FGameplayTag::RequestGameplayTag(FName("GameplayCue.Ability.ChargeStart")),
CueParams);
}
void UGA_ChargedShot::InputReleased(...)
{
// 버튼을 놓으면 차지 완료
if (ChargeTask)
{
ChargeTask->CompleteCharge();
}
}
void UGA_ChargedShot::OnChargeComplete(float ChargeTime)
{
float ChargePercent = FMath::Clamp(ChargeTime / MaxChargeTime, 0.f, 1.f);
float DamageMultiplier = FMath::Lerp(
MinDamageMultiplier, MaxDamageMultiplier, ChargePercent);
// 발사 로직
FireShot(DamageMultiplier);
EndAbility(...);
}
03
채널링 어빌리티
지속 효과 발동
채널링 구현
void UGA_ChanneledBeam::ActivateAbility(...)
{
if (!CommitAbilityCost(...)) { EndAbility(...); return; }
// 채널링 중 마나 소모 Effect (Periodic)
ApplyGameplayEffectToOwner(..., ManaDrainEffect, ...);
// 빔 스폰
SpawnBeamActor();
// 주기적 데미지 Task
UAbilityTask_Repeat* RepeatTask = UAbilityTask_Repeat::RepeatAction(
this, 0.1f, -1); // 0.1초 간격, 무한
RepeatTask->OnPerformAction.AddDynamic(
this, &UGA_ChanneledBeam::OnChannelTick);
RepeatTask->ReadyForActivation();
// 입력 릴리즈 대기
UAbilityTask_WaitInputRelease* ReleaseTask =
UAbilityTask_WaitInputRelease::WaitInputRelease(this);
ReleaseTask->OnRelease.AddDynamic(
this, &UGA_ChanneledBeam::OnInputReleased);
ReleaseTask->ReadyForActivation();
}
void UGA_ChanneledBeam::OnChannelTick(int32 ActionNumber)
{
// 빔 라인트레이스
FHitResult Hit;
if (PerformBeamTrace(Hit))
{
// 타겟에 데미지
ApplyDamageToTarget(Hit.GetActor());
}
// 마나 체크
if (GetMana() <= 0)
{
EndAbility(...);
}
}
void UGA_ChanneledBeam::OnInputReleased(float TimeHeld)
{
EndAbility(...);
}
채널링 취소 조건
채널링은 입력 릴리즈, 마나 소진, 스턴 등 여러 조건으로 취소될 수 있습니다. 태그 기반 취소 조건을 활용하세요.
SUMMARY
핵심 요약
- InputReleased() 오버라이드로 버튼 릴리즈 감지
- 차징: 시간에 비례한 데미지 배율
- 채널링: Periodic Effect로 지속 비용 소모
- WaitInputRelease Task로 입력 종료 대기
- GameplayCue로 차지/채널 시각 피드백
04
차징 레벨과 GE 연동
차징 단계별 GameplayEffect 적용
C++
// 차징 레벨에 따른 GE 선택
void UGA_ChargeAttack::ReleaseCharge()
{
float ChargeRatio = CurrentChargeTime / MaxChargeTime;
int32 ChargeLevel = FMath::Clamp(
FMath::FloorToInt(ChargeRatio * 3), 0, 2);
FGameplayEffectSpecHandle SpecHandle =
MakeOutgoingGameplayEffectSpec(
ChargeLevelEffects[ChargeLevel], ChargeLevel + 1);
// SetByCaller로 차징 배율 전달
SpecHandle.Data->SetSetByCallerMagnitude(
DamageMultiplierTag, 1.f + ChargeRatio * 2.f);
ApplyGameplayEffectSpecToTarget(
GetCurrentAbilitySpecHandle(),
GetCurrentActorInfo(),
GetCurrentActivationInfo(),
SpecHandle, TargetData);
}
네트워크 차징 주의
차징 시간은 서버에서 계산하세요. 클라이언트의 CurrentChargeTime을 신뢰하면 조작 가능합니다. WaitInputRelease Task 완료 시 서버에서 최종 차징 레벨을 결정하세요.
PRACTICE
도전 과제
배운 내용을 직접 실습해보세요
실습 1: 3단계 차징 어빌리티
UAbilityTask_WaitInputRelease로 버튼 릴리즈를 감지하고, 차징 시간에 따라 약/중/강 3단계로 구분하세요. 각 단계에서 다른 UAnimMontage와 GameplayCue를 실행하세요.
실습 2: 채널링 빔 어빌리티
InputReleased()를 오버라이드하여 버튼 홀드 동안 지속되는 빔을 구현하세요. Periodic GE로 0.5초마다 마나를 소모하고, 마나 부족 시 CancelAbility()로 자동 종료하세요.
심화 과제
차징 중 GameplayCue로 시각 피드백(파티클 크기 증가, 색상 변화)을 구현하고, SetByCaller Magnitude로 차징 배율을 GE에 전달하세요. 오버차징 시 자기 데미지를 주는 리스크 시스템도 추가하세요.