LineTrace undefined behavior when starting from hit, confirmed bug

Here’s a paint drawing to illustrate how my bullet penetration system functions:

image

Here is a in-game image of the issue:

Black lines are incoming bullets, orange are the bullet re-route, and green are distance check.

Sometimes the orange line has length of zero, despite hitting the same wall with a slightly different angle than other orange lines.

I got the orange line to function SOMETIMES by setting bTraceComplex and bIgnoreTouches to true in FCollisionQueryParams of the line trace, but it still fails completely randomly.

I looked into this a bit more, and it seems more and more like a bug. Originally I used LineTraceSingleByChannel, but if I use LineTraceMultiByChannel, the trace only ever gives a single hit result, that being the starting point.
This could also be some weird trickery with FCollisionQueryParams that im not aware of, but any feedback would be appreciated.

Here’s the code for the orange line trace:

FCollisionQueryParams Params;
Params.AddIgnoredActor(this);
Params.AddIgnoredActor(Owner);
Params.bFindInitialOverlaps = true;
Params.bTraceComplex = true;
Params.bIgnoreTouches = true;

/* First trace */
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, LastTraceEnd, ECollisionChannel::ECC_WorldStatic, Params))
{
	DrawDebugLine(GetWorld(), Start, Hit.ImpactPoint, FColor::Black, true, 5, 0U, 5);

	float MaxDistance = (Start - LastTraceEnd).Length();			// Max distance of a trace with nothing in between
	float DistanceBeforeHit = (Start - Hit.ImpactPoint).Length();	// Trace distance before hit
	float NewDistance = MaxDistance - DistanceBeforeHit;			// Distance we need to trace

	// TODO: Check how this randomness should actually work, current is fine
	FRotator Random = { FMath::RandRange(-0.5f, 0.5f), FMath::RandRange(-0.5f, 0.5f), FMath::RandRange(-0.5f, 0.5f) };
	CurrentDirection = Random.RotateVector(CurrentDirection);

	FVector SecondaryStart = Hit.ImpactPoint;;
	LastTraceEnd = SecondaryStart + CurrentDirection;

	/* Penetration trace re-route */
	TArray<FHitResult> SecondaryHit;
	GetWorld()->LineTraceMultiByChannel(SecondaryHit, SecondaryStart, LastTraceEnd, ECollisionChannel::ECC_WorldStatic, Params);
	if (SecondaryHit.Num() >= 1) 
	{
		// First hit is ALWAYS same as with fist trace, which might be a bug.
		// Anyway, we ignore everything except second hit

		DrawDebugLine(GetWorld(), SecondaryStart, SecondaryHit[0].ImpactPoint, FColor::Orange, true, 5, 0U, 5);

		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Re-route hit something!"));
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Size: %i"), SecondaryHit.Num()));

		BulletCollisions(MaxDistance, SecondaryStart, Params);

Try adding the slightest offset to the start of the orange trace (move it along it’s normal). It could be catching the “start” wall and prematurely ending giving it zero length.

Thanks, this allows orange line to always have correct lenght, but if the penetration starts in a tight angle of a small corner, the added normal will move the orange start beyond the end of the penetration. I’ll check if I can fix this.

However, this seems to prove that it’s a bug, TraceMulti shouldn’t terminate like this.

You could add consecutive actors to Params.AddIgnoredActor but this would not allow for ricochets on corners of the same mesh.

Edit: you could do the normal shift only when the length of the returned hit location to start is equal to 0 (would need a second trace though). It would just cover the edge case.

It’s not a perfect solution: Bullet animations now “jump” between the two traces, which aren’t perfectly aligned anymore, so ricochet of a bullet looks wacky.

But penetration and else works the same.