UE 5 스터디/Gameplay Ability System(GAS)

24-14. 감전사 스펠 - (8) 구형 범위 이내 근접한 적 찾기

Crat3 2025. 3. 7. 18:49

0. 개요

첫 타격 대상 주위의 다른 적을 감지하여 감전사 스펠이 뻗어 나가도록 구현한다.

 

 

1. 체인 라이트닝

(1) AuraBeamSpell 어빌리티에서 멤버 변수와 함수 선언

첫 대상 주위의 다른 적을 감지하고 해당 적들을 배열에 담아, 각 대상에 대해 게임플레이 큐 파라미터를 만들 것이다.

	UPROPERTY(EditDefaultsOnly, Category = "Beam")
	int32 MaxNumShockTargets = 5;

 

	UFUNCTION(BlueprintCallable)
	void StoreAdditionalTarget(TArray<AActor*>& OutAdditionalTargets);

 

 

(2) Aura 어빌리티 시스템 라이브러리 - 가장 가까운 타겟 찾기 함수

	UFUNCTION(BlueprintCallable, category = "AuraAbilitySystemLibrary|GameplayMechanics")
	static void GetClosestTargets(int32 MaxTargets, const TArray<AActor*>& Actors, TArray<AActor*>& OutClosestTargets, const FVector& Origin);
void UAuraAbilitySystemLibrary::GetClosestTargets(int32 MaxTargets, const TArray<AActor*>& Actors, TArray<AActor*>& OutClosestTargets, const FVector& Origin)
{
	// 찾으려는 타겟이 대상들보다 많으면 그대로 전달
	if (Actors.Num() <= MaxTargets)
	{
		OutClosestTargets = Actors;
		return;
	}

	TArray<AActor*> ActorsToCheck = Actors;
	int32 NumCheck = 0;

	while (NumCheck < MaxTargets)
	{
    		if (ActorsToCheck.Num() == 0)
			break;
            
		double ClosestDistance = TNumericLimits<double>::Max();
		AActor* ClosestActor;
		for (AActor* Actor : ActorsToCheck)
		{
			const double Distance = (Origin - Actor->GetActorLocation()).Length();
			if (ClosestDistance > Distance)
			{
				ClosestDistance = Distance;
				ClosestActor = Actor;
			}
		}
		ActorsToCheck.Remove(ClosestActor);
		OutClosestTargets.AddUnique(ClosestActor);
		NumCheck++;
	}
}

배열을 복사하여 원점에서 가장 가까운 거리와 액터를 저장한다.

복사한 배열에서 가장 근접한 액터를 제거하고, 내보낼 배열에 해당 액터를 집어넣는다.

 

 

(3) AuraBeamSpell의 근접한 타겟을 배열로 저장하는 함수

void UAuraBeamSpell::StoreAdditionalTarget(TArray<AActor*>& OutAdditionalTargets)
{
	TArray<AActor*> ActorsToIgnore;
	ActorsToIgnore.Add(GetAvatarActorFromActorInfo());
	ActorsToIgnore.Add(MouseHitActor); // 이미 빔에 맞고 있기 때문에 제외

	// 구형 오버랩
	TArray<AActor*> OverlappingActors;
	UAuraAbilitySystemLibrary::GetLivePlayersWithinRadius(
		GetAvatarActorFromActorInfo(),
		OverlappingActors,
		ActorsToIgnore,
		850.f, // 탐색 반경
		MouseHitActor->GetActorLocation());

	// int32 NumAdditionalTargets = FMath::Min(GetAbilityLevel() - 1, MaxNumShockTargets);
	int32 NumAdditionalTargets = 5;

	// 가장 근접한 대상 찾음
	UAuraAbilitySystemLibrary::GetClosestTargets(
		NumAdditionalTargets,
		OverlappingActors,
		OutAdditionalTargets,
		MouseHitActor->GetActorLocation());
}

이전에 라이브러리에서 만들었던 함수를 사용하여 구형 쿼리를 실시하고, 해당 범위 내의 살아있는 적을 추적한다.

추적된 액터들 대상으로 마우스 포인트 지점에서 가장 근접한 대상을 찾는다.

 

 

(4) GA_Electrocute 이벤트 그래프