PART 4 - 강의 2/4
AbilityTask 커스터마이징
비동기 어빌리티 작업 구현
01
AbilityTask란?
비동기 작업의 빌딩 블록
AbilityTask는 어빌리티 내에서 비동기 작업을 처리하는 클래스입니다. 몽타주 재생, 입력 대기, 이벤트 대기 등 시간이 걸리는 작업을 델리게이트 기반으로 처리합니다.
내장 AbilityTask 예시
- PlayMontageAndWait - 몽타주 재생 및 완료 대기
- WaitGameplayEvent - 특정 GameplayEvent 대기
- WaitInputPress/Release - 입력 이벤트 대기
- WaitDelay - 지정 시간 대기
- WaitTargetData - 타겟팅 데이터 대기
02
커스텀 Task 구조
기본 클래스 구현
커스텀 AbilityTask 정의
UCLASS()
class UAbilityTask_WaitForCharge : public UAbilityTask
{
GENERATED_BODY()
public:
// 델리게이트 선언
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
FOnChargeComplete, float, ChargeTime);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnChargeCancelled);
UPROPERTY(BlueprintAssignable)
FOnChargeComplete OnChargeComplete;
UPROPERTY(BlueprintAssignable)
FOnChargeCancelled OnChargeCancelled;
// 팩토리 메서드 (필수)
UFUNCTION(BlueprintCallable, Category = "Ability|Tasks",
meta = (HidePin = "OwningAbility",
DefaultToSelf = "OwningAbility",
BlueprintInternalUseOnly = "TRUE"))
static UAbilityTask_WaitForCharge* CreateTask(
UGameplayAbility* OwningAbility,
float MaxChargeTime,
float ChargeRate = 1.0f);
// 오버라이드 함수
virtual void Activate() override;
virtual void TickTask(float DeltaTime) override;
virtual void OnDestroy(bool bInOwnerFinished) override;
// 외부 인터페이스
UFUNCTION(BlueprintCallable)
void CancelCharge();
UFUNCTION(BlueprintCallable)
void CompleteCharge();
protected:
float MaxChargeTime;
float ChargeRate;
float CurrentChargeTime;
bool bIsCharging;
};
03
Task 구현
팩토리와 라이프사이클
Task 구현
UAbilityTask_WaitForCharge* UAbilityTask_WaitForCharge::CreateTask(
UGameplayAbility* OwningAbility,
float InMaxChargeTime,
float InChargeRate)
{
// NewAbilityTask 매크로로 생성
UAbilityTask_WaitForCharge* Task =
NewAbilityTask<UAbilityTask_WaitForCharge>(OwningAbility);
Task->MaxChargeTime = InMaxChargeTime;
Task->ChargeRate = InChargeRate;
Task->CurrentChargeTime = 0.f;
Task->bIsCharging = false;
return Task;
}
void UAbilityTask_WaitForCharge::Activate()
{
Super::Activate();
bIsCharging = true;
CurrentChargeTime = 0.f;
// Tick 활성화
bTickingTask = true;
}
void UAbilityTask_WaitForCharge::TickTask(float DeltaTime)
{
Super::TickTask(DeltaTime);
if (!bIsCharging) return;
CurrentChargeTime += DeltaTime * ChargeRate;
// 최대 차지 시간 도달
if (CurrentChargeTime >= MaxChargeTime)
{
CurrentChargeTime = MaxChargeTime;
bIsCharging = false;
if (ShouldBroadcastAbilityTaskDelegates())
{
OnChargeComplete.Broadcast(CurrentChargeTime);
}
EndTask();
}
}
void UAbilityTask_WaitForCharge::CompleteCharge()
{
if (bIsCharging)
{
bIsCharging = false;
if (ShouldBroadcastAbilityTaskDelegates())
{
OnChargeComplete.Broadcast(CurrentChargeTime);
}
EndTask();
}
}
void UAbilityTask_WaitForCharge::OnDestroy(bool bInOwnerFinished)
{
bIsCharging = false;
Super::OnDestroy(bInOwnerFinished);
}
04
Task 사용
어빌리티에서 활용
어빌리티에서 Task 사용
void UGA_ChargedShot::ActivateAbility(...)
{
// Task 생성
UAbilityTask_WaitForCharge* ChargeTask =
UAbilityTask_WaitForCharge::CreateTask(this, 2.0f, 1.0f);
// 델리게이트 바인딩
ChargeTask->OnChargeComplete.AddDynamic(
this, &UGA_ChargedShot::OnChargeComplete);
ChargeTask->OnChargeCancelled.AddDynamic(
this, &UGA_ChargedShot::OnChargeCancelled);
// Task 활성화 (필수!)
ChargeTask->ReadyForActivation();
}
void UGA_ChargedShot::OnChargeComplete(float ChargeTime)
{
float DamageMultiplier = FMath::Lerp(1.0f, 3.0f,
ChargeTime / MaxChargeTime);
FireShot(DamageMultiplier);
EndAbility(...);
}
ReadyForActivation 필수
Task 생성 후 반드시 ReadyForActivation()을 호출해야 합니다. 호출하지 않으면 Task가 시작되지 않습니다.
SUMMARY
핵심 요약
- AbilityTask: 어빌리티 내 비동기 작업 처리
- NewAbilityTask 매크로로 팩토리 메서드 구현
- bTickingTask = true로 Tick 활성화
- ShouldBroadcastAbilityTaskDelegates() 체크 후 브로드캐스트
- ReadyForActivation() 호출 필수
PRACTICE
도전 과제
배운 내용을 직접 실습해보세요
실습 1: 커스텀 AbilityTask 생성
UAbilityTask를 상속하여 일정 거리 이내의 적을 감지하는 UAbilityTask_WaitTargetInRange를 구현하세요. TickTask에서 거리 체크 후 델리게이트를 브로드캐스트하세요.
실습 2: Task 라이프사이클 관리
Activate(), OnDestroy(), ExternalCancel()을 구현하고, ReadyForActivation() 호출 시점을 확인하세요. 어빌리티 종료 시 Task가 자동 정리되는지 확인하세요.
심화 과제
undefined