Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd391ed6ff | ||
|
|
cdfb24a2b1 | ||
|
|
7930be38bb |
No files matched your search
@@ -10,6 +10,10 @@
|
||||
#include "InputMappingContext.h"
|
||||
#include "Engine/World.h"
|
||||
#include "TimerManager.h"
|
||||
#include "Containers/Ticker.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Misc/CommandLine.h"
|
||||
#include "Misc/Parse.h"
|
||||
|
||||
AGigLineCharacter::AGigLineCharacter()
|
||||
{
|
||||
@@ -120,6 +124,31 @@ void AGigLineCharacter::BeginPlay()
|
||||
StartLocation = GetActorLocation();
|
||||
StartRotation = GetActorRotation();
|
||||
|
||||
// The PlayerStart sits above grade so the capsule cannot spawn embedded, so
|
||||
// the BeginPlay position is mid-air. Re-capture once the pawn has landed,
|
||||
// otherwise Reset drops the player 1.4 m back into the air every press.
|
||||
// Repeat until the first grounded frame. A single late timer is wrong: it can
|
||||
// fire after the player (or the QA self-test) has already started walking,
|
||||
// which recorded a mid-stride position as "start".
|
||||
GetWorldTimerManager().SetTimer(SettleHandle, [this]()
|
||||
{
|
||||
if (bQATestWalking)
|
||||
{
|
||||
return; // keep waiting; the test walks almost immediately
|
||||
}
|
||||
if (const UCharacterMovementComponent* Mov = GetCharacterMovement())
|
||||
{
|
||||
if (Mov->IsMovingOnGround())
|
||||
{
|
||||
StartLocation = GetActorLocation();
|
||||
StartRotation = GetActorRotation();
|
||||
GetWorldTimerManager().ClearTimer(this->SettleHandle);
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine: start captured on ground at Z %.0f"),
|
||||
StartLocation.Z);
|
||||
}
|
||||
}
|
||||
}, 0.25f, true);
|
||||
|
||||
// Force game input mode + focus + mouse capture so keyboard/mouse reach the
|
||||
// pawn regardless of window focus quirks.
|
||||
if (APlayerController* PC = Cast<APlayerController>(GetController()))
|
||||
@@ -167,6 +196,154 @@ void AGigLineCharacter::BeginPlay()
|
||||
bHit && Hit.GetActor() ? *Hit.GetActor()->GetActorLabel() : TEXT("none"));
|
||||
}
|
||||
}, 1.0f, true);
|
||||
|
||||
if (FParse::Param(FCommandLine::Get(), TEXT("qaselftest")))
|
||||
{
|
||||
StartQASelfTest();
|
||||
}
|
||||
}
|
||||
|
||||
void AGigLineCharacter::StartQASelfTest()
|
||||
{
|
||||
// Driven by a core ticker rather than a world timer on purpose: pausing the
|
||||
// game stops world timers, so a timer-based test would freeze the moment it
|
||||
// proved pause works.
|
||||
struct FQAState
|
||||
{
|
||||
float Elapsed = 0.0f;
|
||||
FVector Start = FVector::ZeroVector;
|
||||
FVector WalkEnd = FVector::ZeroVector;
|
||||
float Step = 0.0f;
|
||||
bool bWalkMoved = false;
|
||||
bool bResetReturned = false;
|
||||
bool bPausedOn = false;
|
||||
bool bUnpausedBack = false;
|
||||
};
|
||||
|
||||
TSharedPtr<FQAState> State = MakeShared<FQAState>();
|
||||
State->Start = GetActorLocation();
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: start XYZ=(%.0f,%.0f,%.0f)"),
|
||||
State->Start.X, State->Start.Y, State->Start.Z);
|
||||
|
||||
FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateWeakLambda(this,
|
||||
[this, State](float DeltaTime)
|
||||
{
|
||||
State->Elapsed += DeltaTime;
|
||||
const float E = State->Elapsed;
|
||||
|
||||
// 1.0 - 3.0 s: hold forward. Reset sets the Step marker so each phase
|
||||
// runs exactly once without an ever-growing if-chain.
|
||||
if (E >= 1.0f && State->Step < 1.0f)
|
||||
{
|
||||
State->Step = 1.0f;
|
||||
// Measure from the settled position, not the mid-air spawn point.
|
||||
State->Start = GetActorLocation();
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: settled XYZ=(%.0f,%.0f,%.0f)"),
|
||||
State->Start.X, State->Start.Y, State->Start.Z);
|
||||
bQATestWalking = true;
|
||||
}
|
||||
if (bQATestWalking)
|
||||
{
|
||||
AddMovementInput(GetActorForwardVector(), 1.0f);
|
||||
}
|
||||
|
||||
// 3.0: stop and measure.
|
||||
if (E >= 3.0f && State->Step < 2.0f)
|
||||
{
|
||||
State->Step = 2.0f;
|
||||
bQATestWalking = false;
|
||||
State->WalkEnd = GetActorLocation();
|
||||
const float Walked = FVector::Dist2D(State->Start, State->WalkEnd);
|
||||
State->bWalkMoved = Walked > 200.0f; // >2 m in 2 s at 4 m/s
|
||||
UE_LOG(LogTemp, Log,
|
||||
TEXT("GigLine QA: walk moved %.0f cm in 2 s -> %s (Z %.0f -> %.0f)"),
|
||||
Walked, State->bWalkMoved ? TEXT("PASS") : TEXT("FAIL"),
|
||||
State->Start.Z, State->WalkEnd.Z);
|
||||
}
|
||||
|
||||
// 3.5: reset should return to the spawn point.
|
||||
if (E >= 3.5f && State->Step < 3.0f)
|
||||
{
|
||||
State->Step = 3.0f;
|
||||
ResetToStart();
|
||||
}
|
||||
if (E >= 4.0f && State->Step < 4.0f)
|
||||
{
|
||||
State->Step = 4.0f;
|
||||
const float Back = FVector::Dist(State->Start, GetActorLocation());
|
||||
State->bResetReturned = Back < 100.0f;
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: reset returned %.0f cm from spawn -> %s"),
|
||||
Back, State->bResetReturned ? TEXT("PASS") : TEXT("FAIL"));
|
||||
}
|
||||
|
||||
// 4.5: pause, then confirm the world actually stopped.
|
||||
if (E >= 4.5f && State->Step < 5.0f)
|
||||
{
|
||||
State->Step = 5.0f;
|
||||
TogglePause();
|
||||
State->bPausedOn = UGameplayStatics::IsGamePaused(this);
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: pause -> paused=%d %s"),
|
||||
State->bPausedOn ? 1 : 0, State->bPausedOn ? TEXT("PASS") : TEXT("FAIL"));
|
||||
}
|
||||
|
||||
// 5.5: unpause and confirm it comes back.
|
||||
if (E >= 5.5f && State->Step < 6.0f)
|
||||
{
|
||||
State->Step = 6.0f;
|
||||
TogglePause();
|
||||
State->bUnpausedBack = !UGameplayStatics::IsGamePaused(this);
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: unpause -> paused=%d %s"),
|
||||
UGameplayStatics::IsGamePaused(this) ? 1 : 0,
|
||||
State->bUnpausedBack ? TEXT("PASS") : TEXT("FAIL"));
|
||||
}
|
||||
|
||||
// 6.0: ground transect - sweep both sidewalks and the carriageway and
|
||||
// count holes, so "can traverse the block without falling through"
|
||||
// is measured rather than assumed.
|
||||
if (E >= 6.0f && State->Step < 7.0f)
|
||||
{
|
||||
State->Step = 7.0f;
|
||||
UWorld* W = GetWorld();
|
||||
int32 Holes = 0, Samples = 0;
|
||||
float Lowest = 1.0e9f, Highest = -1.0e9f;
|
||||
static const float Lanes[] = {-1400.0f, -167.0f, 1000.0f}; // N walk, road, S walk
|
||||
for (float LaneY : Lanes)
|
||||
{
|
||||
for (float X = -14900.0f; X <= -9420.0f; X += 200.0f)
|
||||
{
|
||||
FHitResult Hit;
|
||||
FCollisionQueryParams Q(TEXT("GigLineTransect"), false, this);
|
||||
const bool bHit = W->LineTraceSingleByChannel(Hit,
|
||||
FVector(X, LaneY, 3000.f), FVector(X, LaneY, -3000.f),
|
||||
ECC_Visibility, Q);
|
||||
++Samples;
|
||||
if (!bHit)
|
||||
{
|
||||
++Holes;
|
||||
continue;
|
||||
}
|
||||
Lowest = FMath::Min(Lowest, Hit.ImpactPoint.Z);
|
||||
Highest = FMath::Max(Highest, Hit.ImpactPoint.Z);
|
||||
}
|
||||
}
|
||||
UE_LOG(LogTemp, Log,
|
||||
TEXT("GigLine QA: transect %d samples, %d holes, ground Z %.0f..%.0f -> %s"),
|
||||
Samples, Holes, Lowest, Highest, Holes == 0 ? TEXT("PASS") : TEXT("FAIL"));
|
||||
}
|
||||
|
||||
// 7.0: verdict, then stop ticking.
|
||||
if (E >= 7.0f)
|
||||
{
|
||||
const bool bAllPass = State->bWalkMoved && State->bResetReturned
|
||||
&& State->bPausedOn && State->bUnpausedBack;
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLine QA: RESULT walk=%d reset=%d pause=%d unpause=%d -> %s"),
|
||||
State->bWalkMoved ? 1 : 0, State->bResetReturned ? 1 : 0,
|
||||
State->bPausedOn ? 1 : 0, State->bUnpausedBack ? 1 : 0,
|
||||
bAllPass ? TEXT("PASS") : TEXT("FAIL"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
void AGigLineCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||
|
||||
@@ -38,6 +38,22 @@ protected:
|
||||
void ResetToStart();
|
||||
void TogglePause();
|
||||
|
||||
/**
|
||||
* TEMP QA: scripted walk / reset / pause verification.
|
||||
*
|
||||
* Enabled only by the `-qaselftest` command-line switch, so it never runs in
|
||||
* normal play. It exists because those three behaviours were listed as
|
||||
* "needs a human at the keyboard" and a repeatable headless check beats
|
||||
* waiting for one.
|
||||
*/
|
||||
void StartQASelfTest();
|
||||
|
||||
/** Set while the self-test is driving forward input. */
|
||||
bool bQATestWalking = false;
|
||||
|
||||
/** Repeating timer that captures StartLocation on first ground contact. */
|
||||
FTimerHandle SettleHandle;
|
||||
|
||||
/** Where the player started, so reset returns there rather than the origin. */
|
||||
UPROPERTY()
|
||||
FVector StartLocation = FVector::ZeroVector;
|
||||
|
||||
@@ -6,6 +6,12 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO.
|
||||
|
||||
---
|
||||
|
||||
## 2026-11-08 — Reset was returning to mid-air; QA self-test switch
|
||||
|
||||
- **`ResetToStart()` restored a `StartLocation` captured in `BeginPlay`**, which is the PlayerStart position *above* grade (Z 600) so the capsule never spawns embedded. Every reset therefore dropped the player 1.4 m back into the air. Fix: capture `StartLocation` on the first grounded frame (repeating 0.25 s timer, cleared once captured) — not a one-shot timer, which can fire after the player has already started walking and record a mid-stride position.
|
||||
- **`-qaselftest`** drives the checks headlessly and logs `GigLine QA: ... PASS/FAIL`. It runs on a **core ticker, not a world timer**: pausing the game stops world timers, so a timer-driven test freezes exactly when it proves pause works.
|
||||
- Current results: walk 746 cm / 2 s with Z steady, reset 0 cm from spawn, pause `IsGamePaused()` 1, unpause 0, transect 84 samples / 0 holes (ground Z 317..395).
|
||||
|
||||
## 2026-11-08 — The fall-through was an 8 m invisible box (QA branch)
|
||||
|
||||
- **Symptom:** player "spawned above ground but never fell", sat at Z 909, `fall=0`, `mode=1` (Walking), no fall-through, view looked plausible so it was mistaken for working.
|
||||
|
||||
@@ -86,13 +86,13 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep
|
||||
- [x] Model hero façade for the El Capitan Entertainment Centre site. **Second pass built 2026-11-07** (proportions recalibrated from the 2009 photograph: entablature 3.4 m, parapet 2.2 m, architrave and cornice bands, square pedestals — the first pass had 5.7 m of blank wall above the capitals and read as a warehouse). **First pass built 2026-11-07** (`Tools/hero_facade_build.py` → `Art/blender/hero/hero-facade-2026-11-07.blend` + JSON part report with evidence per part → `Tools/ue_hero_facade_import.py` → `/Game/Hollywood/ElCapitan/SM_HeroFacade`, 1892 tris, 4 materials, placed on the measured building line). Six columns at 4.96 m over the 25.75 m frontage, plinth, three portal flights (5 risers, not the old 8), entablature 2.2 m, parapet 1.6 m with motto band and medallions. **Screenshot approved** (`Screenshots/review-hero-portals`, `review-hero-facade-front/oblique`). Next pass: banner and window placement, then materials.
|
||||
- [x] Model surrounding block frontage. **Done 2026-11-07, screenshots approved.** The five remaining south-side buildings verified for the block (`Geo/verification/2026-11-06-el-capitan-block.md`) are exported in place from the OSM blockout by `Tools/export_block_frontage.py` -> `Tools/ue_import_block_frontage.py` -> `/Game/Hollywood/Frontage/`, and staged by the demo builder: 6922, 6902, 6838 El Capitan Theatre, 6822 Budget, 6806-6820, 6800 Lee Drug. **Adding them exposed a pre-existing placement bug**: UE south is +Y (the south sidewalk is Y +718..+1447) but the hero facade sat at Y -1450 (north side) and X -12024..-9420, i.e. 26 m east of its own footprint and on the wrong side of the street; the two north-side buildings were likewise on the south side. The hero is now at X -13336 / Y +1307 (inside the frontage gap between 6902 and 6838) and the north buildings are back on the north side (Y -1802..-9431). The sun was raised to pitch -62 so both frontages read instead of one being silhouetted.
|
||||
- [x] Model simplified background buildings directly across Hollywood Boulevard. Done 2026-11-07, the two in-scope north-side buildings — TCL Chinese Theatre (SM_TCL_Chinese_Theatre) and Madame Tussaud's (SM_Madame_Tussauds) — taken from the verified OSM blockout volumes and exported with `ue_metric_v1`, with a Y-mirror so they land north of Hollywood Blvd across the street from the hero (TCL spans Unreal Y 1802..9431, Tussaud's 1888..7586; road centreline ≈ 0, hero façade at Y −1450). Staged in the DemoMap as `North_TCL_Chinese` / `North_Madame_Tussauds`; demo shot `review-03-demo-north-buildings` captured. Simple flat facade materials (surfaces are the `0.1.4` patch).
|
||||
- [A] Build sidewalks, roads, and collision meshes. Terrain, road, sidewalks and kerbs exist (`Art/blender/terrain/`, `street/`) and are assembled in `site/site-2026-11-06.blend`; collision and details (crossing markings, kerb radii, aprons) are not built. Ground must follow the DEM: 3.94 m fall along the block, ~2 % crown between the gutters at ±10–11 m from the centreline, north sidewalk higher than south. Kerb height is an unresolved assumption — the DEM does not resolve it (`Geo/verification/2026-11-06-cross-sections.md`).
|
||||
- [A] Build sidewalks, roads, and collision meshes. Terrain, road, sidewalks and kerbs exist (`Art/blender/terrain/`, `street/`) and are assembled in `site/site-2026-11-06.blend`; crossing markings were built 2026-11-07. Ground follows the DEM: 3.94 m fall along the block, north sidewalk higher than south. **Collision done and verified 2026-11-08:** every site mesh is STATIC with `BlockAll`, the terrain is forced complex-as-simple (a bbox proxy had buried the street 8 m deep), and a swept transect of both sidewalks plus the carriageway reports 84 samples, **0 holes**, ground Z 317..395. Remaining: kerb radii at the corners and apron details, and the kerb height is still an assumption — the DEM does not resolve it (`Geo/verification/2026-11-06-cross-sections.md`).
|
||||
- [x] Materials and look development for all exported assets. **Done 2026-11-07, screenshots approved.** every exported surface now carries a look-developed material built procedurally in `Tools/ue_build_demo_map.py` (`ensure_material`): base colour with a world-space noise blend between two shades for large-scale variation, plus an explicit roughness and specular. Set is `M_Asphalt` 0.92, `M_Concrete` 0.88, `M_KerbConcrete` 0.85, `M_Ground` 0.98, `M_RoadPaint` 0.62, `M_FacadeStone` 0.72 (hero façade) and `M_Stucco` 0.86 (TCL, Tussaud's), assigned by mesh and by actor label. Materials are rebuilt on every run so a stale asset cannot mask a look change. The richer texture-based pass (baked/procedural brick, brick_facade and seamless_concrete generators) stays in the `0.1.4` façade patch.
|
||||
|
||||
### Gameplay - active - qa-input-collision-fix (branch `qa-input-collision-fix-0.1.0`)
|
||||
|
||||
- [x] First-person movement, mouse look, and Enhanced Input bindings. Implemented 2026-11-07: `AGigLineCharacter` (C++, 1.75 m capsule, 1.60 m eye camera, 4 m/s walk, mouse look in deg/s, jump) as the default pawn, with five actions and an 11-entry context in `/Game/Input` built by `Tools/ue_create_input_assets.py`. **Not yet confirmed interactively** — launch PIE on `Test/ReviewMap` and walk. Screenshot review pending (`Screenshots/README.md`).
|
||||
- [-] Collision, reset, and pause functionality. Reset (**R**) and pause (**Escape**) are implemented in `AGigLineCharacter` with `/Game/Input/IA_Reset` and `IA_Pause`. **Collision root cause found 2026-11-08:** the "fall-through" was never a fall — the imported `Terrain_DEM` had only a bounding-box simple collision proxy, so the player stood on an invisible lid 8 m above the street (every downward trace hit the terrain at Z 819). Fixed by forcing complex-as-simple collision on the terrain (`UGigLineAssetTools`, C++) and saving the asset; the demo now spawns at `(-13336, -1150, 600)`, lands on the road at Z 456 with the ground probe reporting `Road_Hollywood` at 366. Walking the block, reset and pause still need a human at the keyboard.
|
||||
- [x] Collision, reset, and pause functionality. Reset (**R**) and pause (**Escape**) implemented in `AGigLineCharacter` with `/Game/Input/IA_Reset` and `IA_Pause`. **Collision root cause found 2026-11-08:** the "fall-through" was never a fall — the imported `Terrain_DEM` had only a bounding-box simple collision proxy, so the player stood on an invisible lid 8 m above the street (every downward trace hit the terrain at Z 819). Fixed by forcing complex-as-simple collision on the terrain (`UGigLineAssetTools`, C++) and saving the asset; the demo spawns at `(-13336, -1150, 600)` and lands on the road at Z 456. **Verified 2026-11-08** by a scripted check (`-qaselftest`, core ticker so pause cannot freeze it): walk 761 cm in 2 s with Z steady, reset returns 0 cm from spawn, pause reports `IsGamePaused()` 1, unpause 0 — `RESULT ... PASS`. Writing it found a real bug: `ResetToStart()` teleported to the mid-air PlayerStart (Z 600), dropping the player 1.4 m on every reset; `StartLocation` is now captured on the first grounded frame. A manual smoke test is still worth doing before the release tag.
|
||||
- [x] Build the walkable demo level: terrain, street, and hero facade assembled into one map with a start point on the north sidewalk, so the demo is something a player can walk rather than a review staging. **Built 2026-11-07** by `Tools/ue_build_demo_map.py` → `/Game/Hollywood/DemoMap`: sun/sky, `Hero_Facade`, six site meshes imported with collision (`Terrain_DEM`, `Road_Hollywood`, both sidewalks and both kerbs), and a `Demo_PlayerStart` on the north sidewalk 20 m back from the frontage. Demo views in `Screenshots/demo/` re-rendered and ☑ approved 2026-11-07.
|
||||
- [x] Walkable sidewalks and a designated street crossing. Crossing chosen: mid-block signalised crossing, OSM way 385648319, at 130 m along the block (`Geo/verification/2026-11-06-street-profile.md`). Done 2026-11-07: continental zebra markings (0.5 m bars / 0.5 m gaps, 3 m band) at all three signalised crossings, no collision on the paint; kerbs were already flushed at the crossings. Enablers found on the way: the street surfaces were 100 % down-facing (invisible in engine) — winding flipped; the terrain buried the street — 10.7 m corridor cut around the centreline (sidewalks cover the transition, walk-check 0 holes); LFS-lockable `.blend`/`.umap` check out read-only — builders now chmod before saving and fail loudly. Screenshot ☑ approved 2026-11-07 (`Screenshots/demo/review-demo-crossing`); the corridor renders near-black in shadow — that was the **Fixed daytime lighting** item, now also done.
|
||||
- [x] Fixed daytime lighting and basic ambience. **Done 2026-11-07, screenshots approved.** Demo map now has a fixed daytime rig in `Tools/ue_build_demo_map.py`: sun pitch −50 / yaw 120 (intensity 4, warm 255/245/230, atmosphere sun light), sky light 2.6 with real-time capture, sky atmosphere, height fog (density 0.008), and a manual-exposure post-process volume (min = max brightness 1.0) so a shot cannot wash out or crush to black. Two root causes found while doing it: (a) **Blender flat diffuse colours do not survive the FBX→UE import** — every site mesh arrived white and the terrain arrived with `WorldGridMaterial`, which is what actually made the scene look blown out; explicit `M_Asphalt` / `M_Concrete` / `M_Ground` / `M_RoadPaint` materials are now created and assigned in the demo builder. (b) only **one of the three crossings** was reaching the game: each band was its own object and Blender renamed the duplicates `.001`/`.002`, which site assembly skips; all bands are now one `Crossing_Markings` object. Demo cameras also fixed: street-level sat inside the façade body, and the crossing camera aimed at the wrong crossing (s=36.6 instead of the designated s=130.1 at UE X −14956). Lighting is dynamic-only (`r.AllowStaticLighting=False`, all lights Movable) so the editor's "LIGHTING NEEDS TO BE REBUILT" warning no longer fires. All four demo views approved by the owner.
|
||||
@@ -110,7 +110,7 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep
|
||||
|
||||
### Release checks
|
||||
|
||||
- [ ] Player can traverse both sides of the demo without falling through geometry. Blender pre-check passes: 0 raycast holes along both sidewalks and the designated crossing; worst seam step 15.8 cm at the sidewalk's outer edge (`Art/blender/README.md`). Engine traversal still to be tested.
|
||||
- [x] Player can traverse both sides of the demo without falling through geometry. **Verified 2026-11-08:** Blender pre-check plus an in-engine swept transect (`-qaselftest`) over the north sidewalk, carriageway and south sidewalk from X -14900 to -9420 — 84 samples, 0 holes, ground Z 317..395 (sidewalk 395, road 366, south walk 317). The player spawns at Z 456 and stays there for the whole run (`fall=0`, single Z).
|
||||
- [ ] Building placement, street scale, and site identity checked against references.
|
||||
- [ ] No blocking collision or packaging defects.
|
||||
- [ ] 60 FPS at 1440p on the dev workstation (Bazzite, Ryzen 7 7700X, 64 GB RAM, RTX 5070 Ti 16 GB) using a documented quality preset; record upscaling state; report performance without frame generation.
|
||||
|
||||
@@ -51,3 +51,10 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b
|
||||
| --- | --- |
|
||||
| `render_screenshots.py` / `render_screenshots.sh` | Rebuilds the review map, runs the game, captures the shot list into `Screenshots/` |
|
||||
| `judge_screenshot.py` | Vision-model pre-check: judges a screenshot against an expected-scene description (`--image` + `--expect`, or `--shots` for every shot in the README). Reads `OPENROUTER_API_KEY` from `.env` (ignored). Optional helper — a human must still approve. |
|
||||
|
||||
## Gameplay QA
|
||||
|
||||
| Command | Purpose |
|
||||
| --- | --- |
|
||||
| `UnrealEditor <uproject> /Game/Hollywood/DemoMap -game -qaselftest` | Headless behaviour check: drives forward input for 2 s, then resets and pauses. Logs `GigLine QA: ... PASS/FAIL` lines and a final `RESULT`. Runs only with `-qaselftest`, so normal play is unaffected. |
|
||||
| `GigLine SIM` / `GigLine GROUND` log lines | Emitted every second by `AGigLineCharacter` (TEMP QA): position, fall state, movement mode, and what the ground probe hits underneath. Remove before release. |
|
||||
Reference in new issue
Block a user