qa(collision): seam+wall audit in qaselftest; keep shot actor out of QA mode
- Expand the transect to 1456 samples across 16 rows including the kerb/road/ sidewalk seam Ys (-1382/-1053/+718/+1047 and neighbours), X -20000..-2000. Result: 0 holes, walk/reset/pause all PASS. - Add a wall probe: find ground under each start, then trace 30 m horizontally 160 cm above it. A fixed Z 160 probe started inside the earth (street is at Z ~366) and reported every row as a dist-0 blocker; grounding the probe fixed it. Result: 0/35 blocking hits inside 21 m -> no invisible walls. - GigLineShotActor: skip screenshot rounds under -qaselftest, else it quits the game (bQuitWhenDone) before the transect phase runs.
This commit is contained in:
1 parent
963b3424a4
commit
f0809d6c0f
2 files changed
+65
-3
No files matched your search
@@ -266,10 +266,18 @@ void AGigLineCharacter::StartQASelfTest()
|
|||||||
UWorld* W = GetWorld();
|
UWorld* W = GetWorld();
|
||||||
int32 Holes = 0, Samples = 0;
|
int32 Holes = 0, Samples = 0;
|
||||||
float Lowest = 1.0e9f, Highest = -1.0e9f;
|
float Lowest = 1.0e9f, Highest = -1.0e9f;
|
||||||
static const float Lanes[] = {-1400.0f, -167.0f, 1000.0f}; // N walk, road, S walk
|
// Probed world-space (2026-11-08): N sidewalk -1912..-1053, kerb
|
||||||
for (float LaneY : Lanes)
|
// -1382..-1053, road -1382..+1047, kerb +718..+1047, S sidewalk
|
||||||
|
// +718..+1447. Rows include the kerb/road/sidewalk boundary Ys so
|
||||||
|
// seam gaps are sampled, not just lane centres.
|
||||||
|
static const float Rows[] = {
|
||||||
|
-1750.0f, -1500.0f, -1382.0f, -1280.0f, -1053.0f, -900.0f,
|
||||||
|
-167.0f, 0.0f, 300.0f, 800.0f, 1047.0f, 900.0f, 718.0f,
|
||||||
|
900.0f, 1250.0f, 1447.0f
|
||||||
|
};
|
||||||
|
for (float LaneY : Rows)
|
||||||
{
|
{
|
||||||
for (float X = -14900.0f; X <= -9420.0f; X += 200.0f)
|
for (float X = -20000.0f; X <= -2000.0f; X += 200.0f)
|
||||||
{
|
{
|
||||||
FHitResult Hit;
|
FHitResult Hit;
|
||||||
FCollisionQueryParams Q(TEXT("GigLineTransect"), false, this);
|
FCollisionQueryParams Q(TEXT("GigLineTransect"), false, this);
|
||||||
@@ -289,6 +297,52 @@ void AGigLineCharacter::StartQASelfTest()
|
|||||||
UE_LOG(LogTemp, Log,
|
UE_LOG(LogTemp, Log,
|
||||||
TEXT("GigLine QA: transect %d samples, %d holes, ground Z %.0f..%.0f -> %s"),
|
TEXT("GigLine QA: transect %d samples, %d holes, ground Z %.0f..%.0f -> %s"),
|
||||||
Samples, Holes, Lowest, Highest, Holes == 0 ? TEXT("PASS") : TEXT("FAIL"));
|
Samples, Holes, Lowest, Highest, Holes == 0 ? TEXT("PASS") : TEXT("FAIL"));
|
||||||
|
|
||||||
|
// Invisible-wall / blocking-mesh probe: at each sample, first find
|
||||||
|
// the ground under the start point (vertical raycast), then run a
|
||||||
|
// horizontal trace 160 cm ABOVE that ground along the street row.
|
||||||
|
// A clean street should let the 30 m trace run clear; a short hit
|
||||||
|
// flags an invisible or misplaced blocker. Starting the horizontal
|
||||||
|
// trace at a fixed Z (e.g. 160) is wrong: the street is at Z ~366
|
||||||
|
// there, so a 160 cm probe starts inside the earth (dist 0).
|
||||||
|
int32 Walls = 0, WallSamples = 0;
|
||||||
|
static const float TraceYs[] = {-1400.0f, -167.0f, 1000.0f, -1382.0f, 1047.0f};
|
||||||
|
for (float WallY : TraceYs)
|
||||||
|
{
|
||||||
|
for (float X0 = -19500.0f; X0 <= -3000.0f; X0 += 2500.0f)
|
||||||
|
{
|
||||||
|
FHitResult GroundHit;
|
||||||
|
FCollisionQueryParams GQ(TEXT("GigLineWallGround"), false, this);
|
||||||
|
if (!W->LineTraceSingleByChannel(GroundHit,
|
||||||
|
FVector(X0, WallY, 3000.f), FVector(X0, WallY, -1000.f),
|
||||||
|
ECC_Visibility, GQ))
|
||||||
|
{
|
||||||
|
continue; // no ground under start -> skip
|
||||||
|
}
|
||||||
|
const float ProbeZ = GroundHit.ImpactPoint.Z + 160.f;
|
||||||
|
FHitResult Hit;
|
||||||
|
FCollisionQueryParams Q(TEXT("GigLineWallProbe"), false, this);
|
||||||
|
const bool bHit = W->LineTraceSingleByChannel(Hit,
|
||||||
|
FVector(X0, WallY, ProbeZ),
|
||||||
|
FVector(X0 + 3000.f, WallY, ProbeZ),
|
||||||
|
ECC_Visibility, Q);
|
||||||
|
++WallSamples;
|
||||||
|
if (!bHit) { continue; } // 30 m clear -> good
|
||||||
|
// Starting just above the ground, a hit within 21 m = blocker.
|
||||||
|
if (Hit.Distance < 2100.f)
|
||||||
|
{
|
||||||
|
++Walls;
|
||||||
|
UE_LOG(LogTemp, Log,
|
||||||
|
TEXT("GigLine QA: wall probe short-hit at X %.0f Y %.0f dist %.0f actor=%s"),
|
||||||
|
X0, WallY, Hit.Distance,
|
||||||
|
Hit.GetActor() ? *Hit.GetActor()->GetName() : TEXT("none"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UE_LOG(LogTemp, Log,
|
||||||
|
TEXT("GigLine QA: wall probe %d/%d traces with blocking hit inside 21 m -> %s"),
|
||||||
|
Walls, WallSamples,
|
||||||
|
Walls == 0 ? TEXT("PASS") : TEXT("FAIL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.0: verdict, then stop ticking.
|
// 7.0: verdict, then stop ticking.
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ void AGigLineShotActor::Tick(float DeltaSeconds)
|
|||||||
{
|
{
|
||||||
Super::Tick(DeltaSeconds);
|
Super::Tick(DeltaSeconds);
|
||||||
|
|
||||||
|
// QA mode: the -qaselftest run owns the process (it walks, resets, pauses,
|
||||||
|
// transects, then quits on its own). Skip the screenshot rounds so the game
|
||||||
|
// does not exit mid-test via bQuitWhenDone.
|
||||||
|
if (FParse::Param(FCommandLine::Get(), TEXT("qaselftest")))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (bWaitingForSettle)
|
if (bWaitingForSettle)
|
||||||
{
|
{
|
||||||
SettleCountdown -= DeltaSeconds;
|
SettleCountdown -= DeltaSeconds;
|
||||||
|
|||||||
Reference in new issue
Block a user