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

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);
