test(vehicle): the chassis box and the gravity are both innocent

Four more things measured instead of guessed:

  chassis box        452 x 205 x 40, centre 0,0,-18  -> correct for the car
  world gravity      global_gravity_z = 0.0, and the character falls normally
  spawn height       5 m up: the pawn still climbs, so penetration is not the cause
  mass override      SetMassOverrideInKg at 0.5 s never logged

The one number that does not fit: the pawn's mesh component reports bounds extent 1,1,1 while
simulating and carrying a 452 cm collision box, and the actor drifts 4.8 m sideways while climbing
with no input. A body that simulates with correct collision but degenerate bounds is not the body the
movement component is driving, so the next question is which component owns it and whether
CreateVehicle() runs at all.

The pawn is parked again; the diagnostic logging stays (it is the tool that produced this), and the
evidence is in the 'Vehicle physics' task.
This commit is contained in:
zwitschi committed 2026-11-09 21:06:26 +01:00
1 parent be86ee6d73
commit f29d9d7e49
78 files changed
+114 -78

No files matched your search

+36 -1
View File
@@ -3,6 +3,7 @@
#include "ChaosVehicleWheel.h"
#include "ChaosWheeledVehicleMovementComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "PhysicsEngine/BodySetup.h"
// From the Blender report (Art/blender/vehicle/report.json). Kept as named constants so a
// model change is a compile-time mismatch to fix, not a number buried in a setup call.
@@ -298,17 +299,51 @@ void AGigLineVehicle::Tick(float DeltaSeconds)
DriveStart = GetActorLocation();
}
// A real-car mass. Without it the physics asset's box takes its computed mass, and a light
// body under the vehicle solver is thrown around instead of settling - which is consistent
// with a pawn that launches itself and never creates its wheels.
if (!bMassSet && SettleElapsed > 0.5f)
{
if (USkeletalMeshComponent* Body = GetMesh())
{
Body->SetMassOverrideInKg(NAME_None, 1500.0f, true);
bMassSet = true;
UE_LOG(LogTemp, Warning, TEXT("GigLine vehicle: mass override 1500 kg, mass now %.0f"),
Body->GetMass());
}
}
// One-shot diagnostic: why zero wheels. Wheels are built in CreateVehicle(), which runs only
// when the physics state produced a vehicle, so the useful facts are whether the mesh is
// simulating and whether it carries a physics asset at all.
{
static bool bDiagnosed = false;
if (!bDiagnosed && SettleElapsed > 3.0f && FParse::Param(FCommandLine::Get(), TEXT("probes")))
if (!bDiagnosed && SettleElapsed > 1.5f && FParse::Param(FCommandLine::Get(), TEXT("probes")))
{
bDiagnosed = true;
USkeletalMeshComponent* Body = GetMesh();
const UChaosWheeledVehicleMovementComponent* Wheeled =
Cast<UChaosWheeledVehicleMovementComponent>(GetVehicleMovementComponent());
FString BoxInfo = TEXT("no-box");
if (Body && Body->GetBodySetup() && Body->GetBodySetup()->AggGeom.BoxElems.Num() > 0)
{
const FKBoxElem& Box = Body->GetBodySetup()->AggGeom.BoxElems[0];
BoxInfo = FString::Printf(TEXT("box %.0fx%.0fx%.0f centre %.0f,%.0f,%.0f"),
Box.X, Box.Y, Box.Z, Box.Center.X, Box.Center.Y, Box.Center.Z);
}
FString BoundsInfo = TEXT("no-bounds");
if (Body)
{
const FBoxSphereBounds B = Body->Bounds;
BoundsInfo = FString::Printf(TEXT("bounds origin %.0f,%.0f,%.0f extent %.0f,%.0f,%.0f"),
B.Origin.X, B.Origin.Y, B.Origin.Z, B.BoxExtent.X, B.BoxExtent.Y, B.BoxExtent.Z);
}
UE_LOG(LogTemp, Warning, TEXT("GigLine vehicle geometry: %s | %s"), *BoxInfo, *BoundsInfo);
{
const USkeletalMesh* Asset = Body ? Body->GetSkeletalMeshAsset() : nullptr;
UE_LOG(LogTemp, Warning, TEXT("GigLine vehicle mesh asset: %s"),
Asset ? *Asset->GetName() : TEXT("NONE"));
}
UE_LOG(LogTemp, Warning,
TEXT("GigLine vehicle diag: mesh=%d simulating=%d physasset=%s setups=%d wheels=%d "
"loc=%.0f,%.0f,%.0f"),
@@ -82,5 +82,6 @@ private:
FVector DriveStart = FVector::ZeroVector;
float SettleElapsed = 0.f;
bool bMassSet = false;
bool bSettleReported = false;
};