Letzte Woche haben wir uns Soft- vs Hard-References angeschaut und warum Hard-Refs der Hauptgrund sind, dass dein Projekt langsam lädt. Große Assets auf soft umzustellen senkt deine Level-Ladezeiten drastisch.

Aber es hat einen Haken. Eine Soft-Reference ist nur ein Pfad — das Asset ist noch nicht im Speicher. Beim ersten Zugriff muss irgendwer es tatsächlich von der Festplatte laden. Wenn du das falsch machst, hitched dein Spiel. Heftig.

Schauen wir uns das richtige Muster an.

Die Tick-Katastrophe

Hier ist die Falle in die fast jeder tappt. Du hast eine Soft Object Reference auf ein Inventar-Icon. Du willst es anzeigen. Du ziehst den Pin auf einen Resolve Soft Object Reference-Node — aber das Icon ist noch nicht geladen, also kommt None zurück. Das Icon verschwindet. Verwirrt verkabelst du Load Asset Blocking stattdessen. Icon ist da. Fertig.

Was du gerade getan hast: jedes Mal wenn dieser Node läuft, stoppt der Game-Thread bis die Datei von der Platte gelesen wurde. Auf einer SSD sind das 20ms Stuttering, das du vielleicht nicht bemerkst. Auf einer HDD oder einem langsamen USB-Stick sind das eine halbe Sekunde eingefrorene Frames. Und wenn du das in einen Tick-Event packst — was Anfänger ständig machen — hitched dein Spiel jeden einzelnen Frame.

Load Asset Blocking ist zu 95% das falsche Werkzeug. Nur nutzen, wenn du keine Wahl hast zu warten (z.B. während eines bewussten Loading-Screens).

Das richtige Muster

Der Node den du eigentlich willst ist Async Load Asset (für Soft Object Reference) oder Async Load Class Asset (für Soft Class Reference). Er lädt auf einem Hintergrund-Thread und feuert einen Execution-Pin wenn fertig.

CB0

Drei Dinge die du wissen musst:

  • Es ist ein Latent-Node (das kleine Uhr-Icon). Funktioniert nur in Event-Graphs und Timelines, nicht in Pure Functions.
  • Der Completed-Execution-Pin feuert nachdem der Load fertig ist. Der Rest deines Graphs läuft sofort, parallel — erwarte nicht dass das geladene Objekt schon existiert, bevor Completed triggert.
  • Der Output ist ein generisches Object. Du musst es zu dem Typ casten den du brauchst, bevor du dessen Properties benutzt.

Das ist das ganze Muster. Drei Nodes, kein eingefrorenes Spiel.

Verlier die Reference nicht

Async-Loading hat einen heimtückischen Failure-Mode. Du lädst ein Asset, benutzt es einmal, der Load-Callback ist fertig. In dem Moment in dem deine lokale Variable aus dem Scope fliegt, sammelt Unreal das Asset per Garbage Collection ein — weil nichts mehr eine Hard-Reference darauf hält. Beim nächsten Mal lädst du es erneut.

Der Fix: speichere das geladene Objekt in einer Member-Variable auf etwas, das am Leben bleibt — dein PlayerController, ein GameInstance-Subsystem oder ein Manager-Actor.

CB1

Jetzt bleibt das Icon im Speicher solange der Halter existiert. Wenn du es nicht mehr brauchst (z.B. Inventar wird geschlossen), Variable leeren damit GC aufräumen kann.

Einen Loading-Spinner anzeigen

Bei größeren Assets — neuer Bereich, Cinematic, schwere Waffe — willst du dem Nutzer zeigen dass etwas passiert. Das Muster:

  1. Spinner-Widget anzeigen.
  2. Async Load Asset triggern (oder mehrere parallel — siehe unten).
  3. Bei Completed Spinner ausblenden und auf neuen Content wechseln.

Der Vorteil gegenüber einem blockierenden Load: das Spiel bleibt responsiv. Animationen, Musik, der Spinner selbst — alles tickt weiter. Sogar Input bleibt aktiv. Das ist der Unterschied zwischen „das Spiel ist eingefroren" und „das Spiel lädt".

Mehrere Sachen gleichzeitig laden

Oft brauchst du nicht ein Asset — sondern fünf. Der naive Weg: kette sie auf, lade A, dann B, dann C. Das funktioniert, aber sie laden sequenziell. Gesamtzeit = A + B + C.

Schneller: alle parallel anstoßen und warten bis alle fertig sind. In Blueprints geht das mit dem Asset Manager:

  • Load Asset List (Async) — gib ihm ein Array von Soft Object References. Kehrt zurück wenn alle geladen sind.
  • Load Class Asset List (Async) — dasselbe, für Klassen.

Oder flexibler: mehrere Async Load Asset-Nodes parallel feuern und einen Counter nutzen — bei jedem Start hochzählen, bei jedem Completed runterzählen, bei null bist du fertig.

Gesamtzeit = max(A, B, C). Auf einer SSD mit drei mittleren Assets sind das oft statt 90ms sequenziell nur noch 35ms parallel.

Typische Fehler

  • Async Load Asset im Tick. Auch die Async-Variante ist Verschwendung wenn du sie jeden Frame neu triggerst. Einmal laden, Ergebnis speichern, wiederverwenden.
  • Casten bevor Completed feuert. Der Output ist None bis der Load fertig ist. Immer nach dem Completed-Pin casten.
  • Failure nicht behandeln. Async Load Asset kann None zurückgeben, wenn das Asset fehlt oder verschoben wurde. Mit Is Valid branchen bevor du das Ergebnis nutzt.
  • Async-Loading für winzige Assets. Wenn das Asset 2 KB groß ist und jeden Frame gebraucht wird, mach es einfach zu einer Hard-Reference. Async hat Overhead pro Frame, das lohnt sich nur für große oder seltene Assets.
  • Nicht entladen. Geladene Soft-References bleiben im Speicher bis GC läuft und nichts mehr darauf referenziert. Wer aggressiv cached ohne aufzuräumen hat Hard-References mit Umweg neu erfunden.

So prüfst du dass es funktioniert

Zwei Konsolen-Befehle die du kennen solltest:

  • stat LevelStreaming — zeigt was gerade rein- und rausgestreamt wird.
  • stat MemoryPlatform — aktueller Speicher-Footprint. Vor und nach einem Async-Load ausführen um zu bestätigen, dass das Asset wirklich geladen wurde.

Für tieferen Einblick: Window → Developer Tools → Memory öffnet den Live-Memory-Profiler. Nach deinem Asset-Pfad filtern und du siehst genau, wann es den Speicher betritt und verlässt.

Die 30-Sekunden-Zusammenfassung

  • Load Asset Blocking = Game-Thread blockiert. Nur in bewussten Loading-Screens nutzen.
  • Async Load Asset = Hintergrund-Load, latent, feuert Completed wenn fertig.
  • Ergebnis in einer Member-Variable speichern, sonst frisst GC es.
  • Mehrere Assets? Parallel laden mit Asset Manager oder eigenem Counter.
  • Cast und Is Valid nach Completed, nie vorher.

Wenn du die Soft-Reference-Regeln aus letzter Woche umgesetzt hast und dein Spiel jetzt im Moment des Zugriffs hitched — das hier ist der Fix. Das Ergebnis: ein Projekt das schnell lädt und flüssig läuft.

Nächste Woche ein Schritt zurück zu den Basics. Ich habe bisher recht fortgeschrittene Posts geschrieben — und ein paar Leser haben gefragt „cool, aber wo fange ich überhaupt an?". Berechtigte Frage. Nächsten Sonntag: Dein erstes Unreal-Engine-Projekt — richtig aufgesetzt. Die 30 Minuten Setup die dir Wochen ersparen. Manchmal sind die langweiligen Grundlagen das Nützlichste was ich schreiben kann.

— Marco