Unreal GAS (12) - GameplayEffect Duration Policy (지속 시간 정책)

wnsduf0000·2025년 12월 1일

Unreal_GAS

목록 보기
13/34
  • Gameplay Effect Duration Policy

    • Instant
      • GameplayEffect의 DurationPolicy를 Instant로 설정한 경우에 해당함.
      • 단발성이며, FGameplayAttributeData의 BaseValue를 영구적으로 변화시킴.
    • Duration, Infinite
      • GameplayEffect의 DurationPolicy를 HasDuration 또는 Infinite로 설정한 경우에 해당함.
      • Duration은 Duration Magnitude에 설정한 지속 시간만큼 적용되고 사라지며,
        Infinite는 별도로 제거하지 않는 한 계속해서 유지됨.
      • FGameplayAttributeData의 CurrentValue를 변화시킴.
        (BaseValue를 변화시키지 않음)
    • Periodic
      • GameplayEffect의 DurationPolicy를 HasDuration 또는 Infinite로 설정하고,
        Period의 값이 0보다 크게 설정된 경우에 해당함.
      • Duration Magnitude에 설정된 시간 동안, Period에 설정한 시간 마다 발동함.
        예를 들어, Period가 0.1이고, Duration Magnitude를 Scalable Float로 1.0으로 설정하면,
        1초동안 0.1초마다 효과가 발동됨.
      • Period의 Execute Periodic Effect On Application의 설정 여부에 따라,
        GameplayEffect 적용 즉시 효과를 1회 발동하고 시작할지, 또는 발동하지 않고 시작할지를 결정할 수 있음.
      • Periodic Inhibition Policy는 GameplayTag와 연관된 변수로, GameplayTag에 따라 지속 효과가 적용되지 않도록 할 수 있음.
      • FGameplayAttributeData의 BaseValue를 변화시킴.
  • GameplayEffect Stacking

    • Stacking Type

      • None

        • Stacking을 사용하지 않음.
          단, Stacking을 사용하지 않는다는 의미가 같은 효과를 여러 개 중첩했을 때 중첩되지 않는다는 뜻은 아니며, 오히려 Stacking 관리를 하지 않기 때문에 중첩된 효과들이 개별적으로 전부 적용됨.
      • Aggregate by Source

        • GameplayEffect를 적용시킨 쪽에 따라서 Stack 중첩을 적용함.
          Source는 실제로 이 GameplayEffect를 적용시키는 AbilitySystemComponent를 의미함.
        • 테스트 중에는 BP_HealingCrystal에 의해 GameplayEffect를 적용시켜 체력을 회복하는데,
          액터 자체도 Source로 고려하는 것 같음. (한번에 3개를 획득해도 2개까지만 적용됨)
          이 부분은 추후 테스트가 더 필요할 것 같음.
      • Aggregate by Target

        • GameplayEffect가 적용되는 대상에 따라서 Stack 중첩을 적용함.
        • BP_HealingCrystal에 의해 Aura의 체력이 회복된다면, 이 경우 Target은 Aura를 의미함.
    • Stack Limit Count

      • 최대로 중첩될 수 있는 스택의 수를 지정할 수 있음
    • Stack Duration Refresh Policy / Stack Period Reset Policy

      • None 또는 Refresh on Successful Application (Period의 경우는 Reset on Successful Application) 을 선택할 수 있는데, Stack 적용 중 동일한 GameplayEffect가 적용될 경우, 기존에 적용되던 GameplayEffect의 지속시간(Duration)과 적용 주기(Period)를 어떻게 재설정할 것인지를 선택함.
    • Stack Expiration Policy

      • Clear Entire Stack
        • 효과 지속 시간이 종료될 경우, 모든 스택을 제거함.
      • Remove Single Stack and Refresh Duration
        • 효과 지속 시간이 종료될 경우, 스택을 1개 제거하고 다시 효과를 적용함.
      • Refresh Duration
        • 효과 지속 시간이 종료될 경우, 다시 효과를 적용함.
          이것 자체로는 Duration을 Infinite로 적용한 것과 동일한 효과인데, OnStackCountChange 콜백을 통해 스택이 변할 때의 로직을 따로 구현할 수 있는 방법을 제공함.
  • Infinite Effect Removal

    • Duration이 Infinite로 지정된 GameplayEffect의 경우 별도로 제거를 해 주어야 함.

    • GameplayEffect를 제거하는 함수는 AbilitySystemComponent에서 제공하고 있음.
      RemoveActiveGameplayEffect(FActiveGameplayEffectHandle, int32)

    • 단, Infinite로 설정된 동일한 GameplayEffect가 여러 개 동시에 존재하고 있을 경우, 여러 액터들이 동일한 GameplayEffect에 의해 영향을 받고 있을 때 등의 상황들에 대한 조치를 해 주어야 제대로 제거할 수 있음.

      // ApplyGameplayEffectSpecToSelf()는 FActiveGameplayEffectHandle을 반환함.
      // RemoveGameplayEffect()로 GameplayEffect를 제거하기 위해서 FActiveGameplayEffectHandle에 대한 정보가 필요함.
      // GameplayEffect를 적용받고 있는 액터들 또한 구분하기 위하여 TMap 변수를 생성하여 저장함.
      
      // AuraEffectActor.h
      UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Applied Effect")
      TMap<FActiveGameplayEffectHandle, UAbilitySystemComponent*> ActiveEffectHandles;
      
      // AuraEffectActor.cpp
      // ApplyEffectToTarget()
      const FActiveGameplayEffectHandle ActiveEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());
      const bool bIsInfinite = EffectSpecHandle.Data.Get()->Def.Get()->DurationPolicy == EGameplayEffectDurationType::Infinite;
      if (bIsInfinite && InfiniteEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
      {
      	// TMap 변수에 FActiveGameplayEffectHandle과 타겟 액터를 같이 담아둠.
      	ActiveEffectHandles.Add(ActiveEffectHandle, TargetASC);
      }
      
      // OnEndOverlap()
      if (InfiniteEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
      {
      	UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
      	if (!IsValid(TargetASC)) return;
      
      	TArray<FActiveGameplayEffectHandle> HandlesToRemove;
      
      	// 액터의 AbilitySystemComponent를 확인하고 GameplayEffect를 1스택 제거
      	for (auto HandlePair : ActiveEffectHandles)
      	{
      		if (HandlePair.Value == TargetASC)
      		{
      			TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1);
      			HandlesToRemove.Add(HandlePair.Key);
      		}
      	}
      
      	for (auto& Handle : HandlesToRemove)
      	{
      		ActiveEffectHandles.FindAndRemoveChecked(Handle);
      	}
      }
profile
저는 게임 개발자로 일하고 싶어요

0개의 댓글