다양한 기록

[ChronoSpace] 중력 반전 #1 / SweepMultiByChannel 본문

언리얼 엔진/ChronoSpace

[ChronoSpace] 중력 반전 #1 / SweepMultiByChannel

라구넹 2025. 1. 16. 05:25

어빌리티 추가

 

일단 캐릭터에는 중력 변수가 있는데 폰에는 없음

=> 그냥 Pawn에 AddForce 가해서 중력 반대방향, 하늘로 쏘면 사실상 반중력

 

구역 내의 모든 물체에 힘이 가해져야 하니 multi 처리가 필요하다

FGameplayAbilityTargetDataHandle ACSTA_ReverseGravityTrace::MakeTargetData() const
{
	ACharacter* Character = CastChecked<ACharacter>(SourceActor);

	UAbilitySystemComponent* ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(SourceActor);

	if (!ASC)
	{
		UE_LOG(LogCS, Log, TEXT("ASC Not Found"));
		return FGameplayAbilityTargetDataHandle();
	}
	

	TArray< FHitResult > OutHitResults;
	const float AttackRange = 50.0f;
	const float AttackRaduis = 100.0f;

	FCollisionQueryParams Params(SCENE_QUERY_STAT(UCSAT_ReverseGravityTrace), false, Character);
	const FVector Forward = Character->GetActorForwardVector();
	const FVector Start = Character->GetActorLocation() + Forward * Character->GetCapsuleComponent()->GetScaledCapsuleRadius();
	const FVector End = Start + Forward * AttackRange;

	bool HitDetected = GetWorld()->SweepMultiByChannel(OutHitResults, Start, End, FQuat::Identity, CCHANNEL_CSACTION, FCollisionShape::MakeSphere(AttackRaduis), Params);

	FGameplayAbilityTargetDataHandle DataHandle;
	if (HitDetected)
	{
		for (auto OutHitResult : OutHitResults)
		{
			FGameplayAbilityTargetData_SingleTargetHit* TargetData = new FGameplayAbilityTargetData_SingleTargetHit(OutHitResult);
			DataHandle.Add(TargetData);
		}
	}

#if ENABLE_DRAW_DEBUG
	if (bShowDebug)
	{
		FVector CapsuleOrigin = Start + (End - Start) * 0.5f;
		float CapsultHalfHeight = AttackRange * 0.5f;
		FColor DrawColor = HitDetected ? FColor::Green : FColor::Red;
		DrawDebugCapsule(GetWorld(), CapsuleOrigin, CapsultHalfHeight, AttackRaduis, FRotationMatrix::MakeFromZ(Forward).ToQuat(), DrawColor, false, 5.0f);
	}
#endif

	return DataHandle;
}

타겟 액터에서 SingleData로 하나씩 묶어서 DataHandle 만들고

 

void UCSGA_ReverseGravity::OnTraceResultCallback(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
	int32 idx = 0;
	while (UAbilitySystemBlueprintLibrary::TargetDataHasHitResult(TargetDataHandle, idx))
	{
		FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, idx);
		UE_LOG(LogCS, Log, TEXT("Target %s Detected"), *HitResult.GetActor()->GetName());

		UStaticMeshComponent* StaticMeshComp = Cast<UStaticMeshComponent>(HitResult.GetComponent());

		if (StaticMeshComp)
		{
			UE_LOG(LogCS, Log, TEXT("StaticMeshComp Found!"));
			FVector ZForce(0.0f, 0.0f, 30000.0f);
			StaticMeshComp->AddImpulse(ZForce);
		}
		++idx;
	}

	bool bReplicatedEndAbility = true;
	bool bWasCancelled = false;
	EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled);
}

게임어빌리티에서 결과 받아서 하나씩 까보면서 static mesh이면 힘 가해주기

AddForce는 잘 안떠올라서 AddImpulse를 썼다

 

 

이제 해줘야 할 것은 일정 시간 구역이 반중력 공간이 되는 것

 

현재 테스트용으로 마우스 왼쪽 클릭하면 액션나오도록 해놨는데

쭉 누르고 있으면 마치 영역이 있어서 지속되는 것처럼 발동된다

이 방식을 응용하면 될 것 같다