test(placement): measure the foot contact after the pawn settles, not at spawn

The earlier 'ground 366 against an actor at 561' reading was taken in BeginPlay, while the
pawn is still at its spawn height and falling - so it described the surface far below a
falling capsule, not a float. That number drove two hand-tuned Z values (561 for the player
start, 342 for the car) on the strength of a measurement taken at the wrong moment.

The probe now runs three seconds after spawn, traces from the capsule's feet rather than the
actor origin, and reports three channels with the actor and component each hits. A
multi-channel probe at spawn showed every channel hitting the same StaticMeshActor at 366,
which is consistent with the falling-pawn explanation rather than with missing sidewalk
collision.

Not yet read back: the last two game runs produced no log output at all, so the settled
numbers are unverified and recorded as such.
This commit is contained in:
zwitschi committed 2026-11-09 16:40:54 +01:00
1 parent cc57ad6c02
commit f4c1fed99b
3 files changed
+44 -15

No files matched your search

@@ -340,20 +340,10 @@ void AGigLineCharacter::BeginPlay()
}
}
// Foot-contact diagnostic: how far the body's lowest point sits above the ground.
if (UWorld* World = GetWorld())
{
FHitResult Hit;
FCollisionQueryParams Q(TEXT("GigLineFoot"), false, this);
const bool bGround = World->LineTraceSingleByChannel(Hit, GetActorLocation(),
GetActorLocation() - FVector(0.f, 0.f, 3000.f), ECC_Visibility, Q);
const float CapsuleHalf = GetCapsuleComponent() ? GetCapsuleComponent()->GetScaledCapsuleHalfHeight() : -1.f;
const float MeshBottom = GetMesh() ? (GetMesh()->Bounds.Origin - GetMesh()->Bounds.BoxExtent).Z : 0.f;
UE_LOG(LogTemp, Warning,
TEXT("GigLine foot: actor Z %.0f, ground %.0f, capsule half %.0f, mesh bottom %.0f, gap %.0f cm"),
GetActorLocation().Z, bGround ? Hit.ImpactPoint.Z : -9999.f, CapsuleHalf, MeshBottom,
bGround ? MeshBottom - Hit.ImpactPoint.Z : -9999.f);
}
// Foot-contact diagnostic, one line per channel: the player stands at 561 while the
// Visibility trace reports ground at 366, so at least one channel is seeing a different
// surface than the one under foot. This names the actor and the Z for each channel.
// Foot-contact probe runs from Tick three seconds after spawn — see LogFootProbes().
bWalkForever = FParse::Param(FCommandLine::Get(), TEXT("walk"));
bCameraTest = FParse::Param(FCommandLine::Get(), TEXT("cameratest"));
@@ -380,6 +370,32 @@ FVector AGigLineCharacter::GetThirdPersonCameraLocation() const
return ThirdPersonCamera ? ThirdPersonCamera->GetComponentLocation() : GetActorLocation();
}
void AGigLineCharacter::LogFootProbes()
{
UWorld* World = GetWorld();
if (!World)
{
return;
}
static const TCHAR* Names[] = {TEXT("Visibility"), TEXT("WorldStatic"), TEXT("Pawn")};
static const ECollisionChannel Channels[] = {ECC_Visibility, ECC_WorldStatic, ECC_Pawn};
const float CapsuleHalf = GetCapsuleComponent()
? GetCapsuleComponent()->GetScaledCapsuleHalfHeight() : 0.f;
const FVector Feet = GetActorLocation() - FVector(0.f, 0.f, CapsuleHalf);
for (int32 Index = 0; Index < 3; ++Index)
{
FHitResult Hit;
FCollisionQueryParams Q(TEXT("GigLineFoot"), false, this);
const bool bHit = World->LineTraceSingleByChannel(Hit, Feet + FVector(0.f, 0.f, 5.f),
Feet - FVector(0.f, 0.f, 1500.f), Channels[Index], Q);
UE_LOG(LogTemp, Warning,
TEXT("GigLine foot %s after settling: actor Z %.0f, feet %.0f, hit=%d Z=%.0f actor=%s"),
Names[Index], GetActorLocation().Z, Feet.Z, bHit ? 1 : 0,
bHit ? Hit.ImpactPoint.Z : -9999.f,
bHit && Hit.GetActor() ? *Hit.GetActor()->GetName() : TEXT("none"));
}
}
void AGigLineCharacter::UpdateCameraCollisionTest(float DeltaSeconds)
{
// Deterministic on purpose. Finding a wall in the street wasted four runs: the
@@ -977,6 +993,15 @@ void AGigLineCharacter::Tick(float DeltaSeconds)
UpdateCameraCollisionTest(GetWorld() ? GetWorld()->GetDeltaSeconds() : 0.f);
}
if (FootProbeDelay > 0.f)
{
FootProbeDelay -= GetWorld() ? GetWorld()->GetDeltaSeconds() : 0.f;
if (FootProbeDelay <= 0.f)
{
LogFootProbes();
}
}
WalkForever();
UpdateBodyAnimation();
@@ -210,6 +210,10 @@ protected:
UPROPERTY()
TObjectPtr<class AStaticMeshActor> CameraTestWall;
/** Seconds until the foot-contact probe runs; 0 disables it. */
float FootProbeDelay = 0.f;
void LogFootProbes();
FVector LastWallNormal = FVector::ZeroVector;
bool bCameraTest = false;
bool CameraTestPlaced = false;