fix(vehicle): spawn on the road, not 2.5 m under it

Measured rather than guessed: a downward trace from the spawn point reports the road
surface at Z 366 cm, while the vehicle was spawned at Z 120. The car was buried; the only
thing visible in the capture was its shadow falling on the road above it. Spawn is now
Z 470, the camera aims at 430, and it settles at Z 470.

Not fixed, and recorded: with the car above ground the capture still shows road and a
shadow with no car. Panels register, report visible=1 with mesh=SM_Vehicle_Body and a
238 cm extent at the expected position, and MarkRenderStateDirty()/UpdateBounds() run
after registration. The shadow proves a collider is there; the visible geometry is not.

Screenshots/README.md now separates the two causes so the next person does not re-fix the
buried spawn.
This commit is contained in:
zwitschi committed 2026-11-09 15:33:42 +01:00
1 parent 627737062b
commit 1cddfbfc68
40 files changed
+75 -51

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+22 -2
View File
@@ -77,6 +77,10 @@ void AGigLineVehicle::BuildVisuals()
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Component->SetMobility(EComponentMobility::Movable);
Component->RegisterComponent();
// Runtime-created components need their render state forced: without this the
// panels registered and reported visible but never reached the renderer.
Component->MarkRenderStateDirty();
Component->UpdateBounds();
Panels.Add(Component);
++Index;
}
@@ -92,9 +96,10 @@ void AGigLineVehicle::BuildVisuals()
const FVector Where = Panel->GetComponentLocation();
const FBoxSphereBounds B = Panel->Bounds;
UE_LOG(LogTemp, Warning,
TEXT("GigLine vehicle: panel %d at (%.0f,%.0f,%.0f) visible=%d extent=%.0f"),
TEXT("GigLine vehicle: panel %d at (%.0f,%.0f,%.0f) visible=%d extent=%.0f mesh=%s"),
PanelIndex, Where.X, Where.Y, Where.Z,
Panel->IsVisible() ? 1 : 0, B.BoxExtent.GetMax());
Panel->IsVisible() ? 1 : 0, B.BoxExtent.GetMax(),
Panel->GetStaticMesh() ? *Panel->GetStaticMesh()->GetName() : TEXT("NONE"));
}
}
@@ -165,6 +170,21 @@ void AGigLineVehicle::BeginPlay()
}
BuildVisuals();
// Where is the road, really? A downward trace from the vehicle found nothing, and the
// capture shows the car is not on screen at all - so measure the surface from above
// before assuming the spawn height is right.
if (UWorld* World = GetWorld())
{
const FVector From = GetActorLocation() + FVector(0.f, 0.f, 1000.f);
FHitResult Hit;
FCollisionQueryParams Q(TEXT("GigLineVehicleRoad"), false, this);
const bool bHit = World->LineTraceSingleByChannel(Hit, From,
From - FVector(0.f, 0.f, 4000.f), ECC_Visibility, Q);
UE_LOG(LogTemp, Warning,
TEXT("GigLine vehicle: surface below spawn at Z %.0f cm (hit=%d, actor at %.0f)"),
bHit ? Hit.ImpactPoint.Z : -9999.f, bHit ? 1 : 0, GetActorLocation().Z);
}
// Wheel objects do not exist until the component is registered, so the per-wheel
// flags set in the constructor went nowhere - which is why the drive test measured
// zero speed with throttle held. Apply them again now that they exist, and give the
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -21,7 +21,8 @@ Actionable task list for this project. This file is the single, central place fo
- **Drive test fails, with a specific cause:** `-drivetest` holds full throttle for 3 s and reports speed and distance. Result: `speed=0 cm/s, travelled 2.2 m -> FAIL`, and BeginPlay logs **`0 wheel objects after register`** while the component reports 4 wheel setups. The setups exist but no wheels are created from them, so there is nothing to apply torque to.
- **Next:** confirm the skeleton's bone names match the setups (`Wheel_FL`, `Wheel_FR`, `Wheel_RL`, `Wheel_RR`) - a name mismatch silently produces zero wheels - and give the front and rear pairs their own `UChaosVehicleWheel` subclasses rather than the base class, which is what the setups point at today.
- **Also open:** LOD group wiring, enter/exit, driving route, handling.
- [A] Fix the vehicle not rendering in the scene. **Chased to a strong clue, not yet solved.** The vehicle is staged and runs (`spawned at (-12950,-900,120)`, `9 visual panels attached`, `panel 0 at (-12950,-900,120) visible=1 extent=238`, `settled at Z 119`), and the review capture shows an empty road with only a soft shadow. `Tools/visual_loop.py --verify` passes the frame; `Tools/judge_screenshot.py` returns `verdict=no confidence=1.0`. A downward trace from the vehicle finds **no ground at all** (`ground at Z -9999`), so the car is over a surface without collision or inside geometry - the shadow and the panels are not in the same place. Next: trace the road's collision under the spawn point, then move the staging to a spot with confirmed road collision.
- [A] Fix the vehicle not rendering in the scene. **Chased to a strong clue, not yet solved.** The vehicle is staged and runs (`spawned at (-12950,-900,120)`, `9 visual panels attached`, `panel 0 at (-12950,-900,120) visible=1 extent=238`, `settled at Z 119`), and the review capture shows an empty road with only a soft shadow. `Tools/visual_loop.py --verify` passes the frame; `Tools/judge_screenshot.py` returns `verdict=no confidence=1.0`. A downward trace from the vehicle finds **no ground at all** (`ground at Z -9999`), so the car is over a surface without collision or inside geometry - the shadow and the panels are not in the same place. **Fixed:** the vehicle was spawned 2.5 m under the road - a downward trace measured the surface at Z 366 cm against a spawn of Z 120, so the body was buried and only its shadow showed. The spawn is now Z 470 and it settles there.
- **Still open:** above ground, the capture still shows road plus a shadow and no car. Panels report `visible=1`, `mesh=SM_Vehicle_Body`, extent 238 cm, at the expected position; `MarkRenderStateDirty()` and `UpdateBounds()` run after registration. Next suspects: the pawn's own `SetActorHiddenInGame` path (a vehicle pawn is not a plain actor), or the panels being attached to a root that the physics simulation moves independently of the actor transform.
- [ ] Implement enter/exit interaction.
- [ ] Build a closed driving route with boundaries.
- [ ] Tune basic handling to a drivable state.
+4 -1
View File
@@ -652,7 +652,10 @@ def build():
# configures the Chaos wheels from the modelled dimensions.
vehicle_class = unreal.load_class(None, "/Script/GigLine.GigLineVehicle")
if vehicle_class:
vehicle = spawn(vehicle_class, unreal.Vector(-12950.0, -900.0, 120.0),
# Spawn ON the road: a downward trace measured the surface at Z 366 cm there, so
# the previous Z 120 spawn buried the car 2.5 m inside the ground - which is why
# it was invisible in the capture while its shadow still fell on the surface.
vehicle = spawn(vehicle_class, unreal.Vector(-12950.0, -900.0, 470.0),
"Demo_Vehicle_Sedan")
log(f"staged: Demo_Vehicle_Sedan ({'ok' if vehicle else 'FAILED'})")
else:
+1 -1
View File
@@ -292,7 +292,7 @@ try:
# The sedan, staged on the carriageway at (-12950, -900). Three-quarter front
# view from the road so both the body and the wheels are visible: a side-on
# or rear view hides the wheel stances that the build is judged on.
("demo-vehicle", unreal.Vector(-12250, -1600, 420), unreal.Vector(-12950, -900, 120), 50.0),
("demo-vehicle", unreal.Vector(-12250, -1600, 620), unreal.Vector(-12950, -900, 430), 50.0),
("demo-spawn-view", unreal.Vector(-13336, -3100, 620), unreal.Vector(-13336, 1300, 620), 48.0),
# Street level, from the north sidewalk: the old camera sat at Y -400,
# inside the facade body (which spans Y -1457..-200), so it looked at