Назад к блогу

Unreal Engine World Partition Convert Fix: Как решить проблему бесконечной загрузки и зависания Editor

Опубликовано 7 июня 2026 г.
Unreal Engine World Partition Convert Fix: Как решить проблему бесконечной загрузки и зависания Editor

Коротко о главном

Статья описывает методы устранения зависаний Unreal Engine при конвертации карт в систему World Partition. Основными причинами сбоев являются некорректные координаты акторов, блокировки файловых операций антивирусами или системами контроля версий, а также нехватка оперативной памяти. Для решения проблемы авторы предлагают использовать безопасную конвертацию через Commandlet и проводить предварительный аудит сцены с помощью Python-скрипта.

Вы нажимаете "Convert" в меню World Partition, и ваш Unreal Engine editor мгновенно зависает. Шкала прогресса застывает на 0%, загрузка CPU подскакивает до 100% на одном ядре, и единственным выходом остается принудительное завершение процесса через Task Manager или терминал. Этот цикл бесконечной загрузки при конвертации карт — известная преграда для команд, переводящих старые карты или масштабные прототипы на современную архитектуру пространственного стриминга Unreal Engine. Хотя интерфейс editor UI представляет конвертацию простой операцией в один клик, на нетривиальных уровнях это действие запускает лавину синхронных записей ассетов, выделения памяти под пространственную сетку и циклов сериализации пакетов, с которыми поток editor thread просто не справляется.

Если ваша команда безуспешно пытается применить unreal engine world partition convert fix, решение заключается в том, чтобы полностью обойти editor UI и программно проверить ассеты карты. Ниже мы разберем технические причины сбоев конвертации, расскажем, как безопасно запустить процесс с помощью Unreal commandlet framework, и как автоматизировать предварительные проверки (pre-flight checks), чтобы сэкономить часы отладки.

Под капотом: почему конвертация World Partition вешает ваш Editor

Чтобы исправить зависание при конвертации, нужно сначала понять, что именно пытается сделать Unreal Engine в этот момент. В классических уровнях (.umap) все акторы, свойства и компоненты сериализуются в один монолитный пакет огромного размера. World Partition заменяет эту схему, разбивая уровень на пространственную сетку и сохраняя каждого актора в отдельный файл с помощью системы One File Per Actor (OFPA).

В процессе конвертации движок выполняет три ресурсоемкие операции, на которых чаще всего и происходят сбои:

1. Выделение сетки Spatial Hash и бесконечный цикл координат

Unreal Engine сопоставляет bounding box каждого актора с ячейкой сетки. По умолчанию World Partition использует размер ячейки пространственной сетки 25 600 единиц (256 метров). Если какой-либо актор — например, забытая система частиц, вспомогательный UI-актор или неверно настроенный collision volume — находится на экстремальных координатах (например, X=2,000,000, Y=-5,000,000), движок пытается сгенерировать метаданные для каждой ячейки между началом координат и этим актором. Это вызывает бесконечный цикл выделения памяти, намертво вешая editor при попытке разделить миллионы пустых ячеек.

2. Ограничение скорости диска и блокировки директорий (OFPA)

Конвертация карты с 15 000 акторов означает, что движку нужно создать 15 000 отдельных файлов .uasset внутри папки ExternalActors. В editor этот процесс выполняется синхронно в основном потоке. Если у вас включена интеграция с системой контроля версий (например, Perforce или Git) или активен антивирусный сканер в реальном времени для папок проекта, каждая запись файла перехватывается. Операционная система блокирует дескрипторы файлов, заставляя поток editor thread ждать, что и выглядит как бесконечное зависание.

3. Исчерпание памяти и сбои сериализации пакетов

Во время конвертации editor загружает все зависимые blueprints, static meshes и текстуры в память, чтобы пересчитать границы (bounds) и записать чистые пакеты акторов. При нехватке RAM у движка заканчивается физическая память, и он начинает зависать из-за интенсивного использования файла подкачки. Кроме того, неразрешенные циклические зависимости или поврежденные blueprints могут приводить к серьезным критическим ошибкам упаковки, аналогичным Unreal Package HasValidBlueprint Ensure Crash, что мгновенно останавливает процесс сериализации.


Пошаговое решение 1: Конвертация через Commandlet (безопасный путь)

Никогда не конвертируйте средние и крупные карты через интерфейс Unreal Editor UI. Вместо этого используйте WorldPartitionConvertCommandlet. Запуск конвертации через командную строку изолирует процесс от потока UI editor, позволяет движку более эффективно выполнять Garbage Collection и выводит логи в терминал в реальном времени, что позволяет точно увидеть, на каком акторе происходит зависание.

Создайте bash-скрипт (convert_map.sh) или пакетный файл Windows (convert_map.bat) в папке вашего проекта. Вот надежный, проверенный разработчиками скрипт для Windows:

@echo off
SET "UNREAL_ENGINE_PATH=C:\Program Files\Epic Games\UE_5.5\Engine\Binaries\Win64\UnrealEditor-Cmd.exe"
SET "PROJECT_PATH=D:\Projects\MyGame\MyGame.uproject"
SET "MAP_NAME=/Game/Maps/Campaign_Main"

echo Starting World Partition Conversion for %MAP_NAME%...

"%UNREAL_ENGINE_PATH%" "%PROJECT_PATH%" ^
    -run=WorldPartitionConvertCommandlet ^
    "%MAP_NAME%" ^
    -AllowCommandletRendering ^
    -Force ^
    -Verbose ^
    -stdout ^
    -unattended ^
    -NoShaderCompile ^
    -LOG=WorldPartitionConversion.log

if %ERRORLEVEL% NEQ 0 (
    echo Conversion failed! Check Saved\Logs\WorldPartitionConversion.log
    exit /b %ERRORLEVEL%
)

echo Conversion completed successfully!

Разбор критически важных флагов Commandlet:

  • UnrealEditor-Cmd.exe: Всегда используйте исполняемый файл для командной строки вместо стандартного UnrealEditor.exe. Он выводит логи напрямую в stdout и завершает работу сразу по окончании процесса.
  • -AllowCommandletRendering: Заставляет движок инициализировать ресурсы рендеринга. Это предотвращает зависания, если ваша карта содержит акторы или компоненты, требующие расчета GPU bounds или компиляции материалов во время сериализации.
  • -Force: Указывает конвертеру перезаписывать любые существующие внешние ассеты акторов. Это критично, если предыдущая попытка конвертации зависла на полпути и оставила поврежденные ассеты в директории ExternalActors.
  • -unattended: Подавляет все модальные всплывающие окна и диалоги. Без этого флага конвертация может молча зависнуть в фоне в ожидании нажатия кнопки "OK" в предупреждении о ссылках на ассеты.
  • -NoShaderCompile: Запрещает компилятору Shader запускать новые потоки, что существенно экономит ресурсы CPU и памяти в процессе конвертации.

Пошаговое решение 2: Python-скрипт предварительной проверки (Pre-Flight Verification)

Запуск скрипта конвертации вслепую все еще может завершиться ошибкой, если на карте есть поврежденные данные. Чтобы гарантировать успех, используйте скрипт ниже для аудита пакета карты перед запуском конвертера. Этот Python-скрипт выполняется прямо в Unreal Editor (убедитесь, что плагин Python Editor Script Plugin включен) и проверяет наличие экстремальных координат, пустых акторов и компонентов с высокой плотностью, которые обычно мешают сериализации.

Сохраните этот скрипт под именем wp_preflight_check.py и запустите его через консоль Python или перетащив в окно editor:

import unreal

def validate_map_for_world_partition(map_path, max_boundary_cm=1000000.0):
    """
    Validates a monolithic map asset before converting it to World Partition.
    Scans for null references, extreme actor coordinates, and component counts.
    """
    # Initialize the asset registry to find the target level
    asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()
    map_asset = asset_registry.get_asset_by_object_path(unreal.SoftObjectPath(map_path))
    
    if not map_asset:
        unreal.log_error(f"[PREFLIGHT] Map asset not found at path: {map_path}")
        return False
        
    unreal.log(f"[PREFLIGHT] Loading map package to analyze: {map_path}")
    world = unreal.EditorLoadingAndSavingUtils.load_map(map_path)
    if not world:
        unreal.log_error("[PREFLIGHT] Failed to load the map package into the editor context.")
        return False
        
    # Query all actors currently present in the persistent level
    actors = unreal.GameplayStatics.get_all_actors_of_class(world, unreal.Actor)
    total_actors = len(actors)
    unreal.log(f"[PREFLIGHT] Analyzing {total_actors} actors for potential conversion hazards...")
    
    invalid_actors = 0
    out_of_bounds_actors = []
    heavy_components_actors = []
    
    for actor in actors:
        if not actor or not actor.is_valid():
            invalid_actors += 1
            continue
            
        actor_name = actor.get_actor_label()
        
        # 1. Coordinate Boundary Checks (Detects spatial grid loops)
        location = actor.get_actor_location()
        if (abs(location.x) > max_boundary_cm or 
            abs(location.y) > max_boundary_cm or 
            abs(location.z) > max_boundary_cm):
            out_of_bounds_actors.append((actor_name, location))
            
        # 2. Check for component bloat that leads to serialization hangs
        components = actor.get_all_child_actors(True)
        if len(components) > 150:
            heavy_components_actors.append((actor_name, len(components)))
            
    # Compile the pre-flight report
    unreal.log("------------------ PRE-FLIGHT REPORT ------------------")
    unreal.log(f"Total Actors Audited: {total_actors}")
    
    success = True
    
    if invalid_actors > 0:
        unreal.log_error(f"[FAIL] Found {invalid_actors} invalid/corrupted actors. Clean up your map hierarchy first.")
        success = False
    else:
        unreal.log("[PASS] No corrupted actors found.")
        
    if out_of_bounds_actors:
        unreal.log_warning(f"[WARN] Found {len(out_of_bounds_actors)} actors at extreme coordinates. These will cause infinite spatial grid loops:")
        for name, loc in out_of_bounds_actors:
            unreal.log_warning(f"  -> Actor: '{name}' is at X={loc.x:.1f}, Y={loc.y:.1f}, Z={loc.z:.1f}")
        success = False
    else:
        unreal.log("[PASS] All actors lie within reasonable spatial boundaries.")
        
    if heavy_components_actors:
        unreal.log_warning(f"[WARN] Found {len(heavy_components_actors)} actors with high child/component density:")
        for name, count in heavy_components_actors:
            unreal.log_warning(f"  -> Actor: '{name}' has {count} children (consider merging or nesting)")
            
    unreal.log("-------------------------------------------------------")
    return success

# Execute validation on your target map path
# Example: validate_map_for_world_partition("/Game/Maps/Campaign_Main")

Устранение блокировок Disk I/O и систем контроля версий

Если проверка на Python пройдена успешно, а commandlet все равно зависает, проблема кроется в окружении. Конвертация World Partition создает тысячи файлов физических ассетов внутри структуры папок вашего проекта всего за несколько секунд.

Чтобы решить проблемы с блокировкой диска:

  1. Исключите папки проекта из Real-Time Protection: Откройте Windows Security (или ваш корпоративный антивирус) и добавьте корневую папку проекта в список исключений. Антивирусные сканеры реального времени пытаются проверять каждый файл .uasset при записи в директорию ExternalActors, полностью блокируя очередь диска, из-за чего запись ассетов Unreal аварийно завершается по таймауту.
  2. Временно отключите плагины контроля версий: Перед запуском скрипта конвертации временно переименуйте файлы .uplugin или отключите Perforce/Git в настройках editor. После успешной конвертации карты можно снова включить плагин контроля версий, добавить новую директорию ExternalActors в список изменений и закоммитить.
  3. Запускайте с правами администратора: В некоторых корпоративных средах разработки ограничения на запись в папки мешают commandlets создавать поддиректории на лету, что приводит к немым сбоям записи и зависаниям потоков.

Масштабирование до огромных миров: инфраструктурный уровень

Конвертация карты в World Partition — это лишь первый шаг к работе с огромными координатами и высокодетализированными сценами. Однако разработка игры с большим открытым миром ставит новые сложные задачи перед вашей инфраструктурой Multiplayer.

Когда игровой мир занимает несколько квадратных километров, один инстанс Dedicated Server не может эффективно обрабатывать репликацию, коллизии и физику для каждого игрока. Для поддержания производительности сервера разработчикам приходится удалять ненужные серверу ассеты — процесс, подробно описанный в нашем руководстве по dedicated server asset stripping.

Даже при удалении ассетов огромный мир со временем потребует зонирования серверов и бесшовных переходов игроков. Создание распределенного Backend сервера, который управляет динамическим распределением серверов, Matchmaking между зонами и синхронизацией баз данных в реальном времени — это масштабная задача. Разработчики часто тратят месяцы на написание собственных Load Balancing решений, менеджеров сессий и конвейеров синхронизации БД для поддержки крупных лобби.

Именно здесь на помощь приходит horizOn — готовый Backend-as-a-Service, спроектированный специально для разработчиков Multiplayer-игр. Автоматически управляя сохранением игроков, сессиями с низкой задержкой и синхронизацией состояний на стороне сервера, наша платформа позволяет вашей команде сосредоточиться на игровом процессе и оптимизации производительности клиента, а не на отладке инфраструктуры.


Best Practices по конвертации в World Partition

Следуйте этим 4 проверенным правилам, чтобы обеспечить гладкую конвертацию карт и избежать регрессий:

  1. Сначала явно задайте границы уровня: Всегда размещайте актор ALevelBounds на вашей карте перед конвертацией. Это дает генератору World Partition точные границы (bounding box) для пространственного хэша, не позволяя парсить случайные ассеты на бесконечных координатах.
  2. Устраните циклические зависимости в Blueprints: Убедитесь, что логика ваших уровней в Blueprints не содержит жестких взаимных зависимостей приведений типов (casting) с акторами, переносимыми во внешние файлы. Циклические зависимости заставляют упаковщик перезагружать пакеты в процессе сериализации, что часто вызывает утечки памяти и зависания конвертации.
  3. Выполняйте конвертацию при чистом состоянии движка: Всегда перезагружайте систему или очищайте кэш Shader и DerivedDataCache (DDC) перед началом конвертации больших уровней. Это высвободит оперативную память и гарантирует, что commandlet не споткнется об устаревшие кэшированные ассеты.
  4. Изолируйте папку ExternalActors в Git/Perforce: Убедитесь, что ваши файлы .gitignore или .p4ignore корректно настроены для игнорирования временных файлов блокировки при отслеживании файлов .uasset, созданных в директории ExternalActors.

Готовы масштабировать ваш Multiplayer Backend?

Выполняя конвертацию через commandlets и проверяя положение акторов программным путем, вы легко обойдете зависания editor и продолжите разработку. После того как ваши огромные уровни будут разбиты на секции и оптимизированы, следующим шагом станет обеспечение надежности Backend при высоких нагрузках.

Вместо того чтобы тратить недели на настройку собственного Matchmaking, систем лобби и репликации игрового состояния, доверьте сложную работу horizOn. Попробуйте платформу бесплатно уже сегодня или изучите API docs, чтобы увидеть, насколько просто подключить ее к вашему проекту на Unreal Engine.


Источник: Convert map to world partition not working unreal engine 5.7.4