Files
gig-line/Tools/ue_vehicle_probe_map.py
T
zwitschi fe219b038c test(vehicle): collision is not the cause either - defer the rig to its own session
Third fix tried and failed: the terrain staged in the probe map with collision disabled entirely. The pawn
still rises (Z 315 -> 421), exactly as with collision enabled.

With that, the terrain's convex hull, its collision channel and its collision itself are all eliminated, and
the failure survives in a map whose only difference is the presence of a 279 m static mesh.

The player is unaffected throughout - re-checked after every attempt, still standing on Sidewalk_North_07
at 157 cm - so nothing in the walkable demo regressed.

Deferred rather than guessed, per AGENTS.md: the task is marked deferred with the three failed fixes, the
probe workflow and switches a fresh session inherits, and the next question framed precisely - why a map
containing a collisionless 279 m static mesh changes a physics body's behaviour, which points at streaming,
memory layout or the broadphase rather than at collision authoring.

Generated probe levels deleted; the tools stay.
2026-11-09 22:22:39 +01:00

112 lines
4.2 KiB
Python

"""Add one piece of demo content to ReviewMap and save it as a vehicle probe level.
GIGLINE_PROBE_ASSET=Terrain_DEM [GIGLINE_PROBE_NOCOLLISION=1] <engine>/UnrealEditor-Cmd <uproject> \
-run=pythonscript -script=<repo>/Tools/ue_vehicle_probe_map.py -nullrhi -unattended -nopause
Why: the Chaos pawn falls correctly on ReviewMap's empty floor and is thrown upward everywhere in
DemoMap. Rather than guess which of DemoMap's 593 staged meshes is responsible, add them one group
at a time to the map that works and watch for the moment the pawn stops falling. With no
GIGLINE_PROBE_ASSET set, the level is a plain copy of ReviewMap - the control.
Assets are looked up as /Game/Hollywood/Site/<name> first, then /Game/Hollywood/Buildings/<name>.
Result: /tmp/gigline/vehicle-probe.txt
"""
import os
import unreal
RESULT = "/tmp/gigline/vehicle-probe.txt"
TARGET = "/Game/Test/VehicleProbe"
SOURCE = "/Game/Test/ReviewMap"
SEARCH = ("/Game/Hollywood/Site", "/Game/Hollywood/Buildings",
"/Game/Hollywood/Streets", "/Game/Hollywood/Props")
lines = []
def log(message):
lines.append(str(message))
unreal.log(str(message))
def find_asset(name):
for folder in SEARCH:
path = f"{folder}/{name}"
if unreal.EditorAssetLibrary.does_asset_exist(path):
return path
return None
def main():
wanted = os.environ.get("GIGLINE_PROBE_ASSET", "").strip()
if not unreal.EditorAssetLibrary.does_asset_exist(SOURCE):
log(f"missing source level {SOURCE}")
lines.append("VERDICT: FAIL")
return
target = TARGET
# A level that the previous run left behind cannot always be deleted while the editor holds it,
# so fall back to a suffixed name rather than failing the probe.
for suffix in ("", "_b", "_c", "_d"):
target = TARGET + suffix
if not unreal.EditorAssetLibrary.does_asset_exist(target):
break
unreal.EditorAssetLibrary.delete_asset(target)
if not unreal.EditorAssetLibrary.does_asset_exist(target):
break
if not unreal.EditorAssetLibrary.duplicate_asset(SOURCE, target):
log(f"could not duplicate {SOURCE} -> {TARGET}")
lines.append("VERDICT: FAIL")
return
log(f"duplicated {SOURCE} -> {target}")
unreal.EditorLevelLibrary.load_level(target)
if wanted:
path = find_asset(wanted)
if path is None:
log(f"MISSING asset {wanted} in {SEARCH}")
lines.append("VERDICT: FAIL")
return
mesh = unreal.EditorAssetLibrary.load_asset(path)
actor = unreal.EditorLevelLibrary.spawn_actor_from_class(
unreal.StaticMeshActor, unreal.Vector(0.0, 0.0, 0.0))
comp = actor.get_component_by_class(unreal.StaticMeshComponent)
comp.set_static_mesh(mesh)
actor.set_actor_label(f"Probe_{wanted}")
log(f"staged probe mesh {path} at the origin")
# GIGLINE_PROBE_NOCOLLISION=1 stages the same mesh with no collision at all, which separates
# "this mesh's collision ejects physics bodies" from "this mesh does something else".
if os.environ.get("GIGLINE_PROBE_NOCOLLISION", "").strip() == "1":
comp.set_collision_enabled(unreal.CollisionEnabled.NO_COLLISION)
log("probe mesh collision disabled")
else:
log("control run: no extra content")
vehicle_class = unreal.load_class(None, "/Script/GigLine.GigLineVehicle")
if vehicle_class:
pawn = unreal.EditorLevelLibrary.spawn_actor_from_class(
vehicle_class, unreal.Vector(600.0, 0.0, 300.0))
pawn.set_actor_label("Probe_Vehicle")
log("staged the Chaos pawn at (600, 0, 300)")
else:
log("vehicle class not found")
if unreal.EditorLevelLibrary.save_current_level():
log(f"saved {target}")
lines.append(f"LEVEL: {target}")
lines.append("VERDICT: PASS")
else:
log(f"save failed for {target}")
lines.append("VERDICT: FAIL")
try:
main()
except Exception as exc: # noqa: BLE001
import traceback
log(f"FAILED: {type(exc).__name__}: {exc}")
log(traceback.format_exc())
lines.append("VERDICT: FAIL")
with open(RESULT, "w") as f:
f.write("\n".join(lines) + "\n")