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