"""Empty both Unreal maps before a build, and verify they really are empty. /UnrealEditor-Cmd -run=pythonscript \ -script=/Tools/unreal/ue_recreate_maps.py -nullrhi -unattended -nopause -stdout Why this does not delete the `.umap` files: `LevelEditorSubsystem.new_level()` refuses a path whose package is still in memory, and `EditorAssetLibrary.delete_asset()` leaves the file on disk with the package still registered, so deleting and recreating in one session always returns False. Measured: new_level fresh -> True delete_asset -> True disk file still present -> True new_level again -> False What does work, and is what the maps actually need, is clearing every actor and saving: the builders stage everything they use, so a level with no actors is the blank slate. Anything an experiment left behind - an actor from a probe, a duplicated vehicle, a stale shot camera - is gone, which is the failure this step exists to prevent. Both maps are emptied and saved, and the script reports the actor count it left behind. Result: /tmp/gigline/recreate-maps.txt """ import os import unreal MAPS = ("/Game/Hollywood/DemoMap", "/Game/Test/ReviewMap") RESULT = "/tmp/gigline/recreate-maps.txt" lines = [] def log(message): lines.append(str(message)) unreal.log(str(message)) def make_writable(path): """A .umap under Content/ that is read-only cannot be saved; LFS checks it out that way.""" disk = os.path.join(unreal.Paths.project_content_dir(), path.replace("/Game/", "") + ".umap") try: mode = os.stat(disk).st_mode & 0o777 if not mode & 0o200: os.chmod(disk, 0o644) log(f"{path}: chmod u+w ({oct(mode)} -> 0o644)") except FileNotFoundError: pass def main(): les = unreal.get_editor_subsystem(unreal.LevelEditorSubsystem) for path in MAPS: make_writable(path) if not les.load_level(path): log(f"{path}: could not load, and new_level cannot replace an in-memory package") continue removed = 0 for actor in list(unreal.EditorLevelLibrary.get_all_level_actors()): try: unreal.EditorLevelLibrary.destroy_actor(actor) removed += 1 except Exception: # noqa: BLE001 pass left = len(unreal.EditorLevelLibrary.get_all_level_actors()) saved = unreal.EditorLoadingAndSavingUtils.save_map( unreal.EditorLevelLibrary.get_editor_world(), path) log(f"{path}: cleared {removed} actors, {left} left, save_map {saved}") empty = all(" 0 left" in line for line in lines) lines.append(f"VERDICT: {'PASS' if empty else 'FAIL'}") log(f"maps emptied: {'yes' if empty else 'no'}") 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 handle: handle.write("\n".join(lines) + "\n")