qa: walkable demo fixed — terrain collision root cause, spawn, and a scripted QA pass #7

Closed
zwitschi wants to merge 13 commits from qa-input-collision-fix-0.1.0 into main
pull from: qa-input-collision-fix-0.1.0
Owner

What was wrong

The demo was not walkable, and the reported symptom ("falls through the world") was misdiagnosed.

The player never fell. The imported Terrain_DEM carried only a bounding-box simple collision proxy (Interchange default). A downward trace at every Y through the block hit Demo_Terrain_DEM at exactly Z 819 — the mesh bbox max Z. The whole street sat under an invisible 8 m lid; the pawn stood on the box, looking plausible, fall=0, mode=Walking. All the earlier attempts (cap feet above grade, static mobility, SIMPLE_AND_COMPLEX) were treating symptoms of a box that should not have existed.

Fixes

  • Terrain collision — new UGigLineAssetTools (C++) forces CTF_UseComplexAsSimple on the terrain. UE 5.8 no longer has bUseComplexAsSimpleCollision, and Python cannot set the flag at all. The builder saves the asset, not just the map — the flag lives on the asset, so a map-only save silently reverts it.
  • Spawn — (-13336, -1150, 600): on the north side inside the carved corridor, lands on the road at Z 456. The corridor cut is a half-width (10.7 m) around the road centreline, so the old Y -1700 start was outside it, under uncut terrain.
  • Reset bug (found by the new test) — ResetToStart() restored a StartLocation captured in BeginPlay, i.e. the mid-air PlayerStart at Z 600, dropping the player 1.4 m on every reset. Now captured on the first grounded frame.
  • Rebased onto main (fee26ad), keeping the frontage materials and corrected building placement.
  • HighResShot 1280x720 — 1280 720 is parsed as multiplier 1280 and warns "the high resolution screenshot multiplier is too large for your system".

Verification (-qaselftest, headless)

walk    746 cm in 2 s, Z steady 456   PASS
reset   0 cm from spawn               PASS
pause   IsGamePaused() = 1            PASS
unpause IsGamePaused() = 0            PASS
transect 84 samples, 0 holes, ground Z 317..395   PASS

The transect sweeps the north sidewalk, carriageway and south sidewalk from X -14900 to -9420, closing the "traverse both sides without falling through" release check.

Notes

  • GigLine SIM / GigLine GROUND log lines are TEMP QA and should be removed before the release tag.
  • No visual changes: the review cameras and Screenshots/ are unaffected.
## What was wrong The demo was not walkable, and the reported symptom ("falls through the world") was misdiagnosed. **The player never fell.** The imported `Terrain_DEM` carried only a **bounding-box simple collision proxy** (Interchange default). A downward trace at *every* Y through the block hit `Demo_Terrain_DEM` at exactly **Z 819** — the mesh bbox max Z. The whole street sat under an invisible 8 m lid; the pawn stood on the box, looking plausible, `fall=0`, `mode=Walking`. All the earlier attempts (cap feet above grade, static mobility, SIMPLE_AND_COMPLEX) were treating symptoms of a box that should not have existed. ## Fixes - **Terrain collision** — new `UGigLineAssetTools` (C++) forces `CTF_UseComplexAsSimple` on the terrain. UE 5.8 no longer has `bUseComplexAsSimpleCollision`, and Python cannot set the flag at all. The builder saves the **asset**, not just the map — the flag lives on the asset, so a map-only save silently reverts it. - **Spawn** — `(-13336, -1150, 600)`: on the north side inside the carved corridor, lands on the road at Z 456. The corridor cut is a *half*-width (10.7 m) around the road centreline, so the old Y -1700 start was outside it, under uncut terrain. - **Reset bug (found by the new test)** — `ResetToStart()` restored a `StartLocation` captured in `BeginPlay`, i.e. the mid-air PlayerStart at Z 600, dropping the player 1.4 m on every reset. Now captured on the first grounded frame. - **Rebased onto `main`** (`fee26ad`), keeping the frontage materials and corrected building placement. - **`HighResShot 1280x720`** — `1280 720` is parsed as *multiplier* 1280 and warns "the high resolution screenshot multiplier is too large for your system". ## Verification (`-qaselftest`, headless) ``` walk 746 cm in 2 s, Z steady 456 PASS reset 0 cm from spawn PASS pause IsGamePaused() = 1 PASS unpause IsGamePaused() = 0 PASS transect 84 samples, 0 holes, ground Z 317..395 PASS ``` The transect sweeps the north sidewalk, carriageway and south sidewalk from X -14900 to -9420, closing the "traverse both sides without falling through" release check. ## Notes - `GigLine SIM` / `GigLine GROUND` log lines are TEMP QA and should be removed before the release tag. - No visual changes: the review cameras and `Screenshots/` are unaffected.
zwitschi added 13 commits 2026-11-08 11:54:54 +01:00
Carries the QA fixes for the walkable demo off main onto an error-fixing
branch so a live window can be tested without blocking the clean main.

- GigLineCharacter: hard-reference the Enhanced Input assets via
  ConstructorHelpers so the cooker includes /Game/Input (they were soft-only
  and pruned from the pak -> no inputs bound). Push the mapping context on a
  deferred timer after possession.
- defaultgame.ini: +DirectoriesToAlwaysCook for /Game/Input, Hollywood, Test.
- ue_build_demo_map.py: stage site meshes STATIC with explicit collision
  (QUERY_AND_PHYSICS, WorldStatic, BlockAll); hero facade STATIC; PlayerStart
  moved onto the north sidewalk at Y -1200.
- DemoMap.umap rebuilt with the above.

STATUS: packaged build now logs all input assets ok and grounded=1/Walking,
so falling + input-nil are fixed in the package; the user still hit a stuck
window (no mouse/keys) in one test, so this remains WIP pending a clean
interactive run.
A plain packaged launch (./GigLine.sh with no -map) opened
/Engine/Maps/Templates/OpenWorld — an empty engine template with nothing to
do, which presented as a 'stuck' window with no working mouse/keys. The
GameDefaultMap setting lived in DefaultGame.ini and wasn't taking effect.

Move GameMapsSettings (GameDefaultMap/EditorStartupMap/ServerDefaultMap/
TransitionMap = /Game/Hollywood/DemoMap) into DefaultEngine.ini alongside the
GlobalDefaultGameMode, and drop the stale ReviewMap default from DefaultGame.ini.
Verified: plain ./GigLine.sh now loads /Game/Hollywood/DemoMap, Enhanced Input
initializes, Vulkan window opens.
- ue_import_site.py: auto_generate_collision=True so FBX static meshes get
  real collision geometry (they imported with none -> complex-as-simple had
  nothing to use, player fell through).
- ue_build_demo_map.py: PlayerStart cap raised to Z300 so the capsule feet
  start above the ~Z99-138 terrain surface there (an embedded spawn point is
  rejected -> 'NO PLAYERSTART with positive rating' -> origin fallback).
- Re-imported site meshes + rebuilt DemoMap with the above.

KNOWN-UNRESOLVED: packaged plain launch still spawns the capsule around
Z-123 and falls; downward trace finds no geometry. Map assets are all present
in the pak and referenced; runtime collision behavior needs a visual/interactive
check (headless commandlet traces are unreliable). Investigate on this branch;
do not merge to main.
- ue_import_site.py: switch walkable surfaces (terrain, road, sidewalks) from
  CTF_USE_COMPLEX_AS_SIMPLE to CTF_USE_SIMPLE_AND_COMPLEX so the capsule
  blocks against the auto-generated simple collision as well as triangles.
- Re-imported site meshes, rebuilt DemoMap with the PlayerStart cap at Z300.

Unresolved: packaged plain launch still falls through at spawn in the last
verified run (capsule Z-123 -> -1960, no ground trace hit). User confirms the
site geometry RENDERS (visible in the distance) but the player is not standing
on it. Needs an in-editor/in-window collision verification — headless traces
are unreliable. Continue on this branch; do not merge to main.
- PlayerStart moved to (-10722,-2400,800) clear air, facing the facade.
- Force game input mode + hide cursor at BeginPlay.
- Diagnostics: every-second world/Z/gravity/fall log; one HighResShot at 1.5s.

Verified (packaged, engine log): controller connects to pawn input=yes, ctx
pushed, actions bound, world ticks, gravity -980, but capsule stays Z=909
fall=0 forever and no input fires. Static airborne pawn + no fall + no input
= pawn simulated without an active autonomous local player. Recorded for next
debug; do not merge to main.
The player never fell through - it stood on an invisible 8 m box. The
imported Terrain_DEM carried only a bounding-box simple collision proxy,
so every downward trace in the block hit Demo_Terrain_DEM at Z 819 (the
mesh bbox max) and the road/sidewalk underneath were unreachable. The
view from up there looked plausible, which is why it read as working.

- add UGigLineAssetTools (C++): set complex-as-simple collision on a
  static mesh; UE 5.8 exposes ECollisionTraceFlag, not
  bUseComplexAsSimpleCollision, and Python cannot set it at all.
- builder forces + saves the terrain asset as complex-as-simple (the flag
  lives on the asset, so saving only the .umap loses it).
- spawn (-13336, -1150, 600): inside the carved corridor; lands on the
  road at Z 456 (feet 368 on road top 366).
- HighResShot 1280x720, not "1280 720" (that is multiplier 1280).
- keep SIM + single ground-probe diagnostics (TEMP QA).
The three behaviours listed as "needs a human at the keyboard" are now
verifiable headlessly with -qaselftest (core ticker, so pausing the game
does not freeze the test that proves pause works):

  walk   761 cm in 2 s, Z steady 456   PASS
  reset  0 cm from spawn               PASS
  pause  IsGamePaused() = 1            PASS
  unpause IsGamePaused() = 0           PASS

Writing the test found a real bug: ResetToStart() teleported to a
StartLocation captured in BeginPlay, which is the mid-air PlayerStart
(Z 600) rather than the ground (Z 456), so every reset dropped the
player 1.4 m back into the air. StartLocation is now captured on the
first grounded frame.
84 samples across the north sidewalk, carriageway and south sidewalk
(X -14900..-9420) come back with 0 holes and ground Z 317..395, so the
block is traversable rather than merely spawnable.

TODO: sidewalks/collision item now records the collision state and what
is genuinely left (kerb radii, aprons, kerb-height assumption); the
traversal release check is ticked with the measurement.
Author
Owner

Merged to main as 52b1212 via squash (13 commits, 34 files). Post-merge main is at 52b1212; branch qa-input-collision-fix-0.1.0 is safe to delete once the release tag is cut.

Merged to `main` as **52b1212** via squash (13 commits, 34 files). Post-merge `main` is at 52b1212; branch `qa-input-collision-fix-0.1.0` is safe to delete once the release tag is cut.
zwitschi closed this pull request 2026-11-08 11:56:23 +01:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zwitschi/gig-line#7