fix(collision gate): stop freezing the player on a stale prediction
The owner fell through a surface-only world and hovered in mid-air: log showed 'ready=1 predicted_wait=1' for 50 s. Two causes, both fixed: (1) engaging the gate zeroes velocity, so the predicted-support probe never re-ran and the gate kept waiting on the tile remembered from when the pawn was still moving -- the prediction is now re-derived every tick from the pawn's current pose; (2) a tile the streamer never requests (out of layout, or outside the desired set) could never become ready, so the wait was unbounded -- such tiles are now logged and treated as nonblocking, and any wait is bounded to 2 s with a warning. Repro added to the harness (surface-fall scenario): before, the pawn stops at Z=1315.9 with collision_gate_prediction_deadlock; after, it reaches the ground in 2.25 s at Z=-45.6. Strate crossing still protected: 145.49 s route, max gate wait 0.109 s (limit 10 s). Perf S/M/S/M 24.265/54.262 and 23.947/53.057 s, within repeat noise. Owner and canonical geometry unchanged (44E7C813 / 94B47A1C). Known red, pre-existing and unrelated: VoxelForge.Composer.ParameterRoll still reports false box verdicts in the owner's current single-strate surface layout (5 violations, identical in the baseline). Next round. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
7af8d0e870
commit
0dd45ca410
3 files changed
+697
-35
No files matched your search
@@ -522,11 +522,14 @@ private:
|
||||
void ConfigureHeadlessStreamingTest();
|
||||
void AdvanceHeadlessStreamingTest(FVector& InOutPlayerPosition,
|
||||
FVector& InOutPlayerHeading, APawn* PlayerPawn);
|
||||
void AdvanceHeadlessSurfaceFallTest(FVector& InOutPlayerPosition,
|
||||
FVector& InOutPlayerHeading, APawn* PlayerPawn);
|
||||
void InitializeHeadlessStrateCrossingTest();
|
||||
void AdvanceHeadlessStrateCrossingTest(FVector& InOutPlayerPosition,
|
||||
FVector& InOutPlayerHeading, APawn* PlayerPawn);
|
||||
void ObserveHeadlessStrateCrossingTest(const FVector& PlayerPosition, APawn* PlayerPawn);
|
||||
void MaybeFinishHeadlessStrateCrossingTest();
|
||||
void MaybeFinishHeadlessSurfaceFallTest();
|
||||
void MaybeFinishHeadlessStreamingTest();
|
||||
void RecordTileHash(const FVoxelTileKey& Tile, const FIntVector& OriginVoxels,
|
||||
int32 Step, int32 Cells, int32 BandChunkLo, int32 BandChunkHi,
|
||||
@@ -824,10 +827,14 @@ public:
|
||||
FVoxelTileKey& OutSupportTile) const;
|
||||
|
||||
bool IsTileCollisionReady(const FVoxelTileKey& Tile) const;
|
||||
bool IsCollisionTileUnavailable(const FVoxelTileKey& Tile,
|
||||
const TCHAR*& OutReason) const;
|
||||
bool IsCollisionReadyFromSupportTile(const FVoxelTileKey& CandidateTile,
|
||||
FVoxelTileKey* OutSupportTile = nullptr) const;
|
||||
FVoxelTileKey* OutSupportTile = nullptr,
|
||||
const TCHAR** OutUnavailableReason = nullptr) const;
|
||||
bool IsPlayerSupportCollisionReady(APawn* Pawn, const FVector& PlayerPosition,
|
||||
FVoxelTileKey* OutSupportTile = nullptr) const;
|
||||
FVoxelTileKey* OutSupportTile = nullptr,
|
||||
const TCHAR** OutUnavailableReason = nullptr) const;
|
||||
|
||||
/** Gate pawn movement until its current and, when moving, next support tile have a completed
|
||||
* level-0 RMC collision body. The world tick is installed as the pawn prerequisite in the
|
||||
@@ -997,6 +1004,29 @@ public:
|
||||
double HeadlessStreamingTestBeginSeconds = 0.0;
|
||||
double HeadlessStreamingTestLastElapsedSeconds = 0.0;
|
||||
|
||||
// Explicit owner-layout collision-gate repro. This is a command-line-only harness path: it
|
||||
// places the possessed character above the authored single-strate surface and lets ordinary
|
||||
// CharacterMovement gravity carry it to the generated ground.
|
||||
bool bHeadlessSurfaceFallTest = false;
|
||||
bool bHeadlessSurfaceFallTestStartPlaced = false;
|
||||
bool bHeadlessSurfaceFallTestPassed = false;
|
||||
bool bHeadlessSurfaceFallTestFailed = false;
|
||||
bool bHeadlessSurfaceFallTestExitRequested = false;
|
||||
bool bHeadlessSurfaceFallTestPredictionProbeInjected = false;
|
||||
bool bHeadlessSurfaceFallTestPredictionProbeCleared = false;
|
||||
float HeadlessSurfaceFallTestSpawnHeightVoxels = 20.0f;
|
||||
float HeadlessSurfaceFallTestGroundToleranceVoxels = 4.0f;
|
||||
float HeadlessSurfaceFallTestTimeoutSeconds = 8.0f;
|
||||
float HeadlessSurfaceFallTestPlayerHalfHeightVoxels = 3.52f;
|
||||
float HeadlessSurfaceFallTestTerrainZ = 0.0f;
|
||||
double HeadlessSurfaceFallTestBeginSeconds = 0.0;
|
||||
double HeadlessSurfaceFallTestStartSeconds = 0.0;
|
||||
double HeadlessSurfaceFallTestDistanceCm = 0.0;
|
||||
FVector HeadlessSurfaceFallTestStartPosition = FVector::ZeroVector;
|
||||
FVector HeadlessSurfaceFallTestLastActualPosition = FVector::ZeroVector;
|
||||
FVector HeadlessSurfaceFallTestPredictionProbePosition = FVector::ZeroVector;
|
||||
FString HeadlessSurfaceFallTestFailureReason;
|
||||
|
||||
// Explicit parity evidence. Workers append under the lock; EndPlay writes the compact JSON
|
||||
// after ActiveTaskCount has reached zero, so the dump is a complete worker-side snapshot.
|
||||
bool bTileHashDumpEnabled = false;
|
||||
@@ -1015,6 +1045,7 @@ public:
|
||||
bool bHeadlessStrateCrossingTestFailed = false;
|
||||
bool bHeadlessStrateCrossingTestExitRequested = false;
|
||||
bool bHeadlessStrateCrossingTestGateWasEngaged = false;
|
||||
bool bHeadlessStrateCrossingTestInitialSupportReported = false;
|
||||
int32 HeadlessStrateCrossingTestRequestedPassageIndex = INDEX_NONE;
|
||||
int32 HeadlessStrateCrossingTestPassageIndex = INDEX_NONE;
|
||||
int32 HeadlessStrateCrossingTestUpperStrateIndex = INDEX_NONE;
|
||||
@@ -1050,8 +1081,8 @@ public:
|
||||
bool bSavedCharacterMovementMode = false;
|
||||
bool bSavedPawnMovementActive = false;
|
||||
bool bPawnCollisionGateEngaged = false;
|
||||
bool bPawnGateWaitingForPredictedSupport = false;
|
||||
FVoxelTileKey PawnGatePredictedSupportTile;
|
||||
double PawnGateEngagedAtSeconds = 0.0;
|
||||
bool bPawnGateUnavailableReported = false;
|
||||
bool bPawnGateUnsupportedReported = false;
|
||||
|
||||
// Desired-set membership STAMPÉE : clé → numéro du dernier crossing où la tuile était désirée.
|
||||
|
||||
Reference in new issue
Block a user