Powrót do Bloga

Unreal Engine World Partition Convert Fix: Jak rozwiązać problem nieskończonego ładowania i zawieszania się Editora

Opublikowano 7 czerwca 2026
Unreal Engine World Partition Convert Fix: Jak rozwiązać problem nieskończonego ładowania i zawieszania się Editora

W skrócie

Artykuł szczegółowo wyjaśnia przyczyny zawieszania się Unreal Engine Editora podczas konwersji poziomów na architekturę World Partition. Przedstawia bezpieczną metodę wykonania konwersji przy użyciu wiersza poleceń i dedykowanego Commandletu, co eliminuje ograniczenia wątku UI. Dodatkowo zawiera skrypt weryfikacyjny w języku Python, pozwalający na wykrycie skrajnych współrzędnych aktorów oraz problemów z wydajnością I/O przed samym procesem. Całość uzupełniają najlepsze praktyki w zakresie konfiguracji systemów kontroli wersji i optymalizacji backendu.

Klikasz „Convert” w menu World Partition i Twój Unreal Engine Editor natychmiast się zawiesza. Pasek postępu zamarza na 0%, zużycie procesora skacze do 100% na jednym rdzeniu, a Twoją jedyną opcją jest wymuszenie zamknięcia procesu za pomocą Menedżera zadań lub terminala. Ta pętla nieskończonego ładowania podczas konwersji mapy to znany problem dla zespołów przenoszących starsze mapy (legacy maps) lub prototypy o dużej skali na nowoczesną architekturę spatial streaming w Unreal Engine. Choć UI Editora sprawia, że konwersja wydaje się tak prosta jak kliknięcie w menu, wykonanie jej na bardziej złożonym poziomie wyzwala kaskadę synchronicznych zapisów assetów, alokacji siatki przestrzennej (spatial grid allocations) oraz pętli serializacji pakietów, których główny wątek Editora nie jest w stanie obsłużyć.

Jeśli Twój zespół ma trudności z wdrożeniem unreal engine world partition convert fix, rozwiązaniem jest całkowite pominięcie UI Editora i programistyczny audyt assetów mapy. Poniżej szczegółowo omawiamy techniczne przyczyny tych niepowodzeń konwersji, wyjaśniamy, jak bezpiecznie uruchomić proces konwersji za pomocą Commandletów w Unreal Engine, oraz jak zautomatyzować wstępną weryfikację (pre-flight validation checks), aby zaoszczędzić godziny debugowania.

Under the Hood: Dlaczego konwersja World Partition zawiesza Twój Editor

Aby naprawić zawieszanie się konwersji, musisz najpierw zrozumieć, co Unreal Engine próbuje zrobić po uruchomieniu tego procesu. W klasycznych poziomach (.umap) wszystkie aktory (actors), właściwości i komponenty są serializowane do jednego, wielkiego, monolitycznego pakietu. World Partition zastępuje to rozwiązanie, dzieląc poziom na siatkę przestrzenną i przechowując każdego aktora w osobnym pliku przy użyciu systemu One File Per Actor (OFPA).

Podczas konwersji silnik wykonuje trzy wysoce intensywne operacje, które często kończą się niepowodzeniem:

1. Spatial Hash Grid Allocation i pętla nieskończonych współrzędnych

Unreal Engine mapuje bounding box każdego aktora na komórkę siatki. Domyślnie World Partition używa rozmiaru siatki przestrzennej wynoszącego 25 600 jednostek (256 metrów) na komórkę. Jeśli posiadasz aktora – takiego jak zagubiony system cząsteczek, pomocniczy aktor UI lub błędnie skonfigurowany collision volume – umieszczonego na skrajnych współrzędnych (np. X=2 000 000, Y=-5 000 000), silnik spróbuje wygenerować metadane komórek dla każdej komórki między punktem początkowym a tym aktorem. Wyzwala to pętlę nieskończonej alokacji pamięci, zawieszając Editor podczas prób podzielenia milionów pustych komórek.

2. Disk Throttling i blokady katalogów (OFPA)

Konwersja mapy z 15 000 aktorami oznacza, że silnik musi utworzyć 15 000 pojedynczych plików .uasset wewnątrz katalogu ExternalActors. W Editorze proces ten działa synchronicznie na głównym wątku. Jeśli masz aktywną integrację z systemem kontroli wersji (jak Perforce lub Git) albo antywirus skanujący pliki w czasie rzeczywistym w katalogu projektu, każdy zapis pliku jest przechwytywany. System operacyjny blokuje uchwyty plików (file handles), zmuszając wątek Editora do oczekiwania, co objawia się jako nieskończone zawieszenie.

3. Wyczerpanie pamięci i błędy serializacji pakietów

Podczas konwersji Editor ładuje wszystkie powiązane Blueprints, static meshes i tekstury do pamięci, aby przeliczyć granice (bounds) i zapisać czyste pakiety aktorów. Bez odpowiedniej ilości pamięci RAM silnikowi kończy się pamięć fizyczna i następuje spowolnienie (stall), ponieważ system zaczyna intensywnie korzystać z pliku stronicowania (disk paging). Co więcej, nierozwiązane cykliczne zależności lub uszkodzone Blueprints mogą prowadzić do poważnych błędów pakowania, podobnych do Unreal Package HasValidBlueprint Ensure Crash, co natychmiast zatrzymuje proces serializacji.


Step-by-Step Fix 1: Konwersja za pomocą Commandletu (bezpieczna ścieżka)

Nigdy nie konwertuj średnich ani dużych map za pomocą UI Unreal Editora. Zamiast tego użyj WorldPartitionConvertCommandlet. Uruchomienie konwersji z poziomu wiersza poleceń izoluje proces od wątku UI Editora, pozwala silnikowi na wydajniejsze uruchamianie Garbage Collection i zapewnia podgląd logów w terminalu w czasie rzeczywistym, dzięki czemu widzisz dokładnie, który aktor powoduje zawieszenie.

Utwórz skrypt bash (convert_map.sh) lub skrypt wsadowy Windows (convert_map.bat) wewnątrz folderu projektu. Oto stabilny, rekomendowany dla deweloperów skrypt dla systemu 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!

Wyjaśnienie kluczowych flag Commandletu:

  • UnrealEditor-Cmd.exe: Zawsze używaj pliku wykonywalnego wiersza poleceń zamiast standardowego UnrealEditor.exe. Wypisuje on logi bezpośrednio do stdout i kończy działanie natychmiast po zakończeniu procesu.
  • -AllowCommandletRendering: Zmusza silnik do zainicjowania zasobów renderowania. Zapobiega to zawieszeniom, jeśli mapa zawiera aktorów lub komponenty wymagające obliczeń granic GPU (GPU bounds) lub kompilacji materiałów podczas serializacji.
  • -Force: Nakazuje konwerterowi nadpisanie wszelkich istniejących assetów zewnętrznych aktorów. Jest to kluczowe, jeśli poprzednia próba konwersji zawiesiła się w połowie i pozostawiła uszkodzone pliki w katalogu ExternalActors.
  • -unattended: Blokuje wszystkie wyskakujące okna modalne i komunikaty dialogowe. Bez tego konwersja mogłaby po cichu zatrzymać się w tle, czekając na kliknięcie przycisku „OK” przy ostrzeżeniu o referencji assetu.
  • -NoShaderCompile: Uniemożliwia kompilatorowi Shaderów uruchamianie nowych wątków, co oszczędza sporo zasobów procesora i pamięci podczas konwersji.

Step-by-Step Fix 2: Skrypt weryfikacyjny Python (Pre-Flight Check)

Uruchomienie skryptu konwersji „w ciemno” wciąż może zakończyć się niepowodzeniem, jeśli Twoja mapa zawiera błędne dane. Aby zagwarantować sukces, użyj poniższego skryptu do przeprowadzenia audytu pakietu mapy przed uruchomieniem konwertera. Ten skrypt w języku Python działa wewnątrz Unreal Editora (upewnij się, że wtyczka Python Editor Script Plugin jest włączona) i sprawdza skrajne współrzędne, puste (null) aktory oraz komponenty o wysokiej gęstości, które najczęściej blokują proces serializacji.

Zapisz ten skrypt jako wp_preflight_check.py i uruchom go za pomocą konsoli Python lub przeciągając go do okna Editora:

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")

Rozwiązywanie problemów z blokowaniem I/O dysku i blokadami kontroli wersji

Jeśli test weryfikacyjny Pythona przejdzie pomyślnie, a Commandlet nadal się zawiesza, problem tkwi w środowisku systemowym. Konwersja World Partition w kilka sekund tworzy tysiące fizycznych plików assetów w strukturze katalogów projektu.

Aby rozwiązać problemy z blokowaniem dysku:

  1. Wyklucz katalogi projektu z ochrony w czasie rzeczywistym: Otwórz Zabezpieczenia Windows (lub korporacyjny pakiet antywirusowy) i dodaj folder główny projektu do listy wykluczeń. Skanery antywirusowe działające w czasie rzeczywistym próbują sprawdzić każdy plik .uasset zapisywany w katalogu ExternalActors, co całkowicie blokuje kolejkę dyskową i powoduje przekroczenie limitu czasu (timeout) zapisu plików przez silnik Unreal.
  2. Tymczasowo wyłącz wtyczki kontroli wersji: Przed uruchomieniem skryptu konwersji tymczasowo zmień nazwy plików .uplugin lub wyłącz Perforce/Git w konfiguracji Editora. Po pomyślnym przekonwertowaniu mapy możesz ponownie włączyć wtyczkę kontroli wersji, dodać nowy katalog ExternalActors do listy zmian (changelist) i zatwierdzić (commit).
  3. Uruchom z uprawnieniami administratora: W niektórych korporacyjnych środowiskach programistycznych ograniczenia zapisu w katalogach uniemożliwiają Commandletom tworzenie podkatalogów na bieżąco, co prowadzi do cichych błędów zapisu i zawieszania wątków.

Skalowanie do gigantycznych światów: Kwestia Backendowa

Konwersja mapy do World Partition to pierwszy krok do obsługi ogromnych współrzędnych i bardzo szczegółowych scen. Jednak uruchomienie gry z dużym otwartym światem niesie ze sobą nowe wyzwania dla infrastruktury Multiplayer.

Gdy świat Twojej gry obejmuje kilka kilometrów kwadratowych, pojedyncza instancja Dedicated Server nie jest w stanie wydajnie przetwarzać replikacji, kolizji i fizyki dla każdego gracza. Aby utrzymać wydajność serwera, deweloperzy muszą usuwać niepotrzebne na serwerze assety – proces ten szczegółowo opisujemy w naszym przewodniku dotyczącym dedicated server asset stripping.

Nawet przy usuwaniu zbędnych assetów, ogromny świat ostatecznie wymaga podziału serwera na strefy (server zoning) i płynnych przejść graczy między nimi. Budowa rozproszonego Backendu, który obsługuje dynamiczną alokację serwerów, Matchmaking między strefami i synchronizację bazy danych w czasie rzeczywistym, to gigantyczne przedsięwzięcie. Twórcy gier spędzają miesiące na pisaniu własnych mechanizmów Load Balancing, menedżerów sesji i potoków synchronizacji baz danych, aby obsłużyć lobby na dużą skalę.

W tym miejscu z pomocą przychodzi horizOn, oferując gotowy Backend-as-a-Service zaprojektowany specjalnie dla twórców gier Multiplayer. Dzięki automatycznej obsłudze trwałości danych graczy (player persistence), niskolatencyjnemu zarządzaniu sesjami oraz synchronizacji stanu po stronie serwera, nasza platforma pozwala Twojemu zespołowi skupić się na tworzeniu rozgrywki i optymalizacji wydajności klienta, zamiast na debugowaniu infrastruktury.


Najlepsze praktyki konwersji World Partition

Postępuj zgodnie z tymi 4 sprawdzonymi w bojach wytycznymi, aby zapewnić płynną konwersję map i uniknąć regresji:

  1. Najpierw zdefiniuj wyraźne granice poziomu: Przed konwersją zawsze umieść aktora ALevelBounds na swojej mapie. Zapewni to generatorowi World Partition precyzyjny bounding box dla spatial hash, zapobiegając parsowaniu przypadkowych assetów umieszczonych na nieskończonych współrzędnych.
  2. Wyczyść cykliczne zależności Blueprint: Upewnij się, że Twoje level blueprints nie zawierają ścisłych zależności rzutowania (casting dependencies) z aktorami konwertowanymi na pliki zewnętrzne. Zależności cykliczne zmuszają narzędzie pakujące do przeładowywania pakietów w trakcie serializacji, co często prowadzi do wycieków pamięci i zawieszania konwersji.
  3. Wykonuj konwersję na czystym stanie silnika: Zawsze restartuj system lub czyść cache Shaderów oraz DerivedDataCache (DDC) przed konwersją ogromnych poziomów. Zwalnia to pamięć RAM i gwarantuje, że Commandlet nie zablokuje się na przestarzałych, zbuforowanych assetach.
  4. Odizoluj katalog ExternalActors w Git/Perforce: Upewnij się, że Twoje pliki .gitignore lub .p4ignore są poprawnie skonfigurowane, aby ignorować tymczasowe pliki blokad podczas śledzenia plików .uasset generowanych w katalogu ExternalActors.

Gotowy na skalowanie swojego Backendu Multiplayer?

Uruchamiając konwersje za pomocą Commandletów i programistycznie weryfikując pozycje aktorów, możesz łatwo ominąć zawieszanie się Editora i przejść do dalszego rozwoju gry. Gdy Twoje ogromne poziomy zostaną podzielone i zoptymalizowane, kolejnym krokiem będzie upewnienie się, że Twój Backend poradzi sobie z obciążeniem.

Zamiast spędzać tygodnie na konfigurowaniu własnego Matchmakingu, systemów lobby i replikacji stanu graczy, pozwól, aby horizOn wykonał tę najtrudniejszą pracę. Wypróbuj go za darmo już dziś lub przeczytaj API docs, aby zobaczyć, jak proste jest podłączenie projektu Unreal Engine.


Źródło: Convert map to world partition not working unreal engine 5.7.4