LineTraceMulti example

Is there an example of using LineTraceMulti available? Something demonstrating the trace and then going through the results.

I use a LineTraceMulti for a weapon that pierces pawns but not worldstatic objects (so if a pawn is standing in front of another pawn, they’ll both be hit, but if one of them’s behind a wall, it won’t be.)

Collision setup in DefaultEngine.ini looks like this:

+DefaultChannelResponses=(Channel=ECC_GameTraceChannel4,Name="PiercingWeapon",DefaultResponse=ECR_Overlap,bTraceType=True,bStaticObject=False)

+EditProfiles=(Name="BlockAll",CustomResponses=((Channel="PiercingWeapon",Response=ECR_Block)))

So the PiercingWeapon trace channel response by default produces overlapping (non-blocking) hits, but the BlockAll channel will block it.

I define an alias for my trace channel in MyGame.h:

#define COLLISION_WEAPON_PIERCING	ECC_GameTraceChannel4

In my weapon, I generate a list of hit results using LineTraceMulti:

TArray<FHitResult> AMyGameWeapon::WeaponTrace_Piercing(const FVector& StartTrace, const FVector& EndTrace) const
{
	static FName WeaponFireTag = FName(TEXT("WeaponTrace"));

	// Perform trace to retrieve hit info
	FCollisionQueryParams TraceParams(WeaponFireTag, true, Instigator);
	TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = true;

	TArray<FHitResult> Hits;
	GetWorld()->LineTraceMultiByChannel(Hits, StartTrace, EndTrace, COLLISION_WEAPON_PIERCING, TraceParams);

	return Hits;
}

And then the weapon can iterate through the results, deal damage, spawn decals and hit effects, etc (ProcessInstantFireHit() in this case is pretty much what you’ll find in ShooterGame’s example):

void AMyGameWeapon::FireWeapon_Instant_Piercing()
{
	const FInstantWeaponData InstantConfig = GetCurrentFiringFunctionComponent()->GetInstantConfig();

	const int32 RandomSeed = FMath::Rand();
	FRandomStream WeaponRandomStream(RandomSeed);
	const float CurrentSpread = GetCurrentInstantFireSpread();
	const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);

	const FVector AimDir = GetAdjustedAim();
	const FVector StartTrace = GetCameraDamageStartLocation(AimDir);
	const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
	const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange;

	const TArray<FHitResult> Impacts = WeaponTrace_Piercing(StartTrace, EndTrace);
	for (const FHitResult& Impact : Impacts)
	{
		ProcessInstantFireHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);
	}

	CurrentInstantFireSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentInstantFireSpread + InstantConfig.FiringSpreadIncrement);
}

Hope this helps!