Download

bStartPenetrating always returns false

Hello, I would not bother to ask but I’m really stuck for now.
I try to make some kind of bullet penetration and was thinking about how it would be the best.
So I stumbled across bStartPenetrating and wanted to make so that a trace would start inside the wall
and would end at the impact point and just fire another one with a starting point of 1unit deeper till bStartPenetrating doesn’t return true anymore to get the depth of the wall.
But bStartPenetrating ALWAYS returns true for me. Help me please :frowning:


void ABullet_762::OnHit(AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
 {    
     FCollisionQueryParams TraceParams(FName(TEXT("ShootTrace")), true, this);
     TraceParams.bTraceComplex = true;
     TraceParams.bTraceAsyncScene = true;
     TraceParams.bReturnPhysicalMaterial = true;
     TraceParams.bFindInitialOverlaps = true;
 
     FHitResult HitData(ForceInit);
 
     float distance = 1.f;
 
     GetWorld()->LineTraceSingle(HitData, Hit.ImpactPoint + (GetActorRotation().Vector() * 1.1f), Hit.ImpactPoint, ECC_WorldDynamic, TraceParams);
     
     if (!HitData.bStartPenetrating)
     {
         DrawDebugPoint(GetWorld(), HitData.TraceStart, 8.f, FColor::Red, false, 10.f);
         DrawDebugPoint(GetWorld(), HitData.TraceEnd, 8.f, FColor::Green, false, 10.f);
         GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Green, "NOPE1");
     }
     else
     {
         GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Green, "YAW!");
     }
 
     while (HitData.bStartPenetrating && distance < 2000.f)
     {
         distance++;
         GetWorld()->LineTraceSingle(HitData, Hit.ImpactPoint + (GetActorRotation().Vector() * distance), Hit.ImpactPoint, ECC_Pawn, TraceParams);
         GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Green, FString::SanitizeFloat(distance));
     }
 }

I already tried ECC_Pawn and ECC_StaticWorld

Are you setting the trace to ignore the actor you’re doing the trace in? It might be hitting ‘itself’, doesn’t look like you’re ignoring any actors in that code snippet.

OMG! you could be right… testing it now…

Just letting you know of two handy tools to use for this sort of issue:

  1. Trace Tag: That name you provide for each trace or overlap isn’t just for show – you can use it with the TraceTag console command to see what’s happening in the game world. In your case, TraceTag ShootTrace should let you see the trace as it’s happening in realtime.

  2. Collision Analyzer: TraceTag is handy and all, but it’s not very useful for camera-based traces and it can make your frame rate plummet from too many draw calls if you have a lot of traces happening. The collision analyzer is invoked through the console command canalyzer, which will let you record and see a history of traces based on tag, along with cursory information about what they hit, etc.

-Camille

appreciate your answer! I will test them asap!

I think I have to reset the hitdata somehow… for some reason is the return of HitData.GetComponent()->GetName() the same every time even if the trace doesn’t hit anything anymore…

I made it! … Thanks to everyone!


	FCollisionQueryParams TraceParams(FName(TEXT("ColTrace")), true, this);
	TraceParams.bTraceComplex = true;
	TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = true;

	FHitResult HitData(ForceInit);

	float distance = CollisionComp->GetUnscaledSphereRadius() * 2;
	float penetrationDepth;


	GetWorld()->LineTraceSingle(HitData, Hit.ImpactPoint + (GetActorRotation().Vector() * distance), Hit.ImpactPoint + (GetActorRotation().Vector() * -distance), ECC_MAX, TraceParams);

	while (distance < 2000.f/*MODIFIER*/)
	{

		distance++;
		FHitResult *HitData = new FHitResult(ForceInit);
		GetWorld()->LineTraceSingle(*HitData, Hit.ImpactPoint + (GetActorRotation().Vector() * distance), Hit.ImpactPoint + (GetActorRotation().Vector() * (distance - 1)), ECC_MAX, TraceParams);

		if (HitData->GetComponent())
		{			
			penetrationDepth = (Hit.ImpactPoint - HitData->TraceStart).Size();
			UWorld* const World = GetWorld();
			if (World != NULL)
			{
				ADeathProfitCharacter *pOwner;

				if (Cast<ADeathProfitCharacter>(this->GetOwner()))
				{ 
					pOwner = Cast<ADeathProfitCharacter>(this->GetOwner());
					FActorSpawnParameters SpawnParams;
					SpawnParams.Owner = pOwner;
					SpawnParams.Instigator = pOwner->Instigator;

					FVector SpawnLocation(HitData->TraceStart + (GetActorRotation().Vector() * (CollisionComp->GetUnscaledSphereRadius() * 2)));

					ABullet_762* const Projectile = World->SpawnActor<ABullet_762>(pOwner->ProjectileClass, SpawnLocation, GetActorRotation()/*MAYBE RANDOM?*/, SpawnParams);
					if (Projectile)
					{
						// find launch direction
						FVector const LaunchDir = GetActorRotation().Vector();//ADD current velocity
						Projectile->OverrideVelocity(penetrationDepth);
						Projectile->InitVelocity(LaunchDir/*MODIFIER*/);
						DrawDebugLine(GetWorld(), SpawnLocation, SpawnLocation + GetActorRotation().Vector() * 5.f, FColor::White, false, 10.f);

					}
				}
			}
			delete HitData;
			break;
		}

		delete HitData;
	}
	
	Destroy();

(shot in the left side…)

Doing a line trace in a loop like that looks like a recipe for potential performance disaster. I don’t really see why it would be necessary either. If you could explain fully what it is you’re trying to accomplish, there may be a better way.

By the way, there is a function provided for GetActorRotation().Vector(); use GetActorForwardVector().