qa: make the demo walkable — terrain collision root cause, spawn, scripted QA

The reported fall-through was a misdiagnosis: the player never fell. The
imported Terrain_DEM had only a bounding-box simple collision proxy, so a
downward trace anywhere in the block hit the terrain at Z 819 (the mesh
bbox max) and the street sat under an invisible 8 m lid. Standing on that
box looked plausible, which is why it read as working.

- add UGigLineAssetTools (C++): force CTF_UseComplexAsSimple on a static
  mesh. UE 5.8 dropped bUseComplexAsSimpleCollision and Python cannot set
  the flag; the builder also saves the asset, since the flag lives there
  and a map-only save silently reverts it.
- spawn (-13336, -1150, 600): inside the carved corridor (the cut is a
  10.7 m half-width around the road centreline), lands on the road at 456.
- fix ResetToStart returning to the mid-air PlayerStart captured in
  BeginPlay: StartLocation is now captured on the first grounded frame.
- HighResShot 1280x720 instead of "1280 720", which is a multiplier.
- add -qaselftest: scripted walk/reset/pause on a core ticker plus a
  swept ground transect. Results: walk 746 cm/2 s with Z steady, reset
  0 cm from spawn, pause/unpause 1/0, transect 84 samples 0 holes.
- rebase onto main, keeping the frontage materials and placement fixes.
This commit is contained in:
zwitschi committed 2026-11-08 11:56:19 +01:00
1 parent fee26ade10
commit 52b1212cf3
34 files changed
+591 -92

No files matched your search

+8 -4
View File
@@ -85,7 +85,11 @@ def build():
# component and D/A carry strafe, combined by the character. A 2D value would
# need per-key axis modifiers, and modifiers do not survive the save path here.
ia_move = fresh("IA_Move", unreal.InputAction, unreal.InputAction_Factory)
ia_move.set_editor_property("value_type", unreal.InputActionValueType.AXIS1D)
# Boolean (pressed = 1), not AXIS1D: the C++ handler reads Get<bool>() and
# moves at full walk speed. An axis action from a keyboard key can deliver 0
# depending on the trigger, which showed up as "character stands, W does not
# move" in QA. WASD are four separate per-direction actions below.
ia_move.set_editor_property("value_type", unreal.InputActionValueType.BOOLEAN)
save(ia_move)
ia_look = fresh("IA_Look", unreal.InputAction, unreal.InputAction_Factory)
@@ -107,15 +111,15 @@ def build():
# Two actions feed the one-dimensional move: IA_Move for forward/back, and a
# second action for strafe, both reporting on the value's single component.
ia_strafe = fresh("IA_Strafe", unreal.InputAction, unreal.InputAction_Factory)
ia_strafe.set_editor_property("value_type", unreal.InputActionValueType.AXIS1D)
ia_strafe.set_editor_property("value_type", unreal.InputActionValueType.BOOLEAN)
save(ia_strafe)
ia_back = fresh("IA_MoveBack", unreal.InputAction, unreal.InputAction_Factory)
ia_back.set_editor_property("value_type", unreal.InputActionValueType.AXIS1D)
ia_back.set_editor_property("value_type", unreal.InputActionValueType.BOOLEAN)
save(ia_back)
ia_left = fresh("IA_StrafeLeft", unreal.InputAction, unreal.InputAction_Factory)
ia_left.set_editor_property("value_type", unreal.InputActionValueType.AXIS1D)
ia_left.set_editor_property("value_type", unreal.InputActionValueType.BOOLEAN)
save(ia_left)
# Reset and pause are boolean: one press, no accumulator.