SweepMultiByChannel Returns same Actor multiple times

Hello, I’m having a problem using the function SweepMultiByChannel. I am creating an Sphere using SweepMultiByChannel to detect nearby actors within an specific radius. When I place a pawn actor with basic mesh, collision and object type Pawn, The Sphere generated fills the TArray result with only one actor reference, which is the functionality that I’m trying to accomplish. But when I place an skeletal mesh inside the sphere, the SweepMultiByChannel Function, fills the return array with several references of the same skeletal mesh owner actor. The objective would be to return ONLY ONE reference of EACH actor inside the result array. I’m aware that going through the array and removing duplicated actor references would solve the issue, but this would be extremely inefficient. May be I’m not using the function the right way.
Here is the code that uses the SweepMultiByChannel function:

	/*TArray is the collection that contains all the HitResults*/
	TArray<FHitResult> HitResults;

	/*The Start location of the sphere*/
	FVector StartLocation = GetActorLocation();
	FVector EndLocation = GetActorLocation();

	ECollisionChannel ECC = ECollisionChannel::ECC_Pawn;
	/*Declare the Collision Shape, assign a Sphere shape and set it's radius*/
	FCollisionShape CollisionShape = FCollisionShape::MakeSphere(SphereRadius);


	/*Perform the actual raycast. This method returns true if there is at least 1 hit.*/
	bool bHitSomething = Owner->GetWorld()->SweepMultiByChannel(HitResults, StartLocation, EndLocation, FQuat::FQuat(), ECC, CollisionShape);
		
	/*If the raycast hit a number of objects, iterate through them and print their name in the console*/
	if (bHitSomething)
	{
		for (auto It = HitResults.CreateIterator(); It; It++)
		{
			GLog->Log((*It).Actor->GetName());
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, (*It).Actor->GetName());
			//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, FString::Printf(TEXT("%d"), HitResults.Num())); 

		}
	}

	/*In order to draw the sphere of the first image, I will use the DrawDebugSphere function which resides in the DrawDebugHelpers.h
	This function needs the center of the sphere which in this case is provided by the following equation*/
	FVector CenterOfSphere = ((EndLocation - StartLocation) / 2) + StartLocation;

	/*Draw the sphere in the viewport*/
	DrawDebugSphere(GetWorld(), CenterOfSphere, CollisionShape.GetSphereRadius(), Segments, FColor::Red, true);

In the image is the sphere being generated from a cube, and printed are the actors returned in the array, I painted over the actors that doesn’t matter in this question (cube, floor, projectile, etc)

Hi, if you need only one object shouldn’t you just use SweepSingleByChannel?

Hello, MrMcKvarz, thanks for the quick reply. Maybe I didn’t explain myself correctly, I want the result TArray to have only one reference of each actor detected by the Sphere. If I use SweepSingleByChannel, as per my understanding, it will return only the first actor detected by the trace inside the sphere, isn’t that right? Not sure how SweepSingleByChannel differs from SweepMultiByChannel, could you enlighten me on that matter please?

I couldn’t find anything to help you, apart from setting actors to ignore. I wouldn’t expect it to return multiple instanced of 1 object if you call it once. Do you call it from the tick or something?

I’m not calling it from the Tick, and the other detected actors (floor, wall, ceiling) are being returned only once in the result array. It happens only with actors with skeletal mesh, I was thinking it might have something to do with bones maybe. I’m also digging into the Kismet SphereOverlapActors function, but not sure yet if this function has bigger impact in performance. Thanks again for the answer :slight_smile:

SweepMultiByChannel is returning each component it hits, not just each actor it hits. So, that’s your explanation as to why it returns a bunch of the same actor. Try narrowing down the channel, or using AddIgnoredComponents to try and make it indifferent to any component that may have collision that you don’t care about.

Your only other option is to maybe set up a loop of single sweeps that adds each actor it touches to an ignore list and keeps single-sweeping until it returns NULL, breaking the loop.