Während nicht mehr benötigter Speicher (Garbage) freigegeben wird, steht das ganze Spiel still. Typisch ist Ruckeln in regelmäßigen Abständen.
Warum In jedem Frame entstehen temporäre Strings, Arrays und Listen, die gleich wieder verworfen werden → Folge Hat sich genug Garbage angesammelt, hält die GC den Main-Thread an und räumt auf → Auf dem Bildschirm Regelmäßiges Ruckeln alle paar Sekunden bis alle paar Dutzend Sekunden
Allokationen reduzieren (String-Verkettung, LINQ und Lambda-Captures vermeiden), Object-Pools nutzen, inkrementelle GC eingeschaltet lassen (seit Unity 2020 Standard), die GC vorab dann auslösen, wenn ein Stillstand nicht stört, etwa auf Ladebildschirmen.
Größenordnungen
Meist einige ms bis 100 ms pro Lauf, auf schwachen Smartphones oder bei Spielen mit hohem Speicherbedarf mehr (im Experiment etwa 150–170 ms). Die GC von Unity durchsucht bei jedem Lauf den gesamten Heap. Je mehr Speicher das Spiel belegt, desto länger dauert sie.
Im Graphen
Spitzen in festen Abständen · Frametime, Zeitpunkte der GC-Läufe
Wo nachsehen
In einem Development-Build die Marker GC.Collect und GC.Alloc im Unity Profiler ansehen. In Unreal stat GC und stat Hitches (protokolliert Frames, die länger als der mit t.HitchFrameTimeThreshold festgelegte Wert dauern)
Spricht dafür
Jeder Ausreißer-Frame enthält einen GC.Collect-Abschnitt von etwa der Länge des Ausschlags, die Abstände sind regelmäßig und liegen bei einigen bis einigen Dutzend Sekunden. An belebten Orten steigt GC.Alloc pro Frame
Spricht dagegen
Kein GC-Abschnitt im Ausreißer-Frame: „Synchrones Laden und Shader-Kompilierung im Main-Thread“ oder „Renderlast durch große Spielermengen“
Prüfmittel
Logs oder Metriken aus Spielserver bzw. Client nötig
Mehr dazu
Häufig bei Clients mit C#, etwa in Unity. Hauptverursacher ist Code, der Kampflog-Texte, Schadenszahlen und UI-Texte in jedem Frame neu erzeugt. Ruckelt es nur an belebten Orten, gibt es Code, dessen Garbage mit der Spielerzahl wächst. Die inkrementelle GC sammelt pro Frame nur ein Stück (Unity-Standard 3 ms). Entsteht Garbage schneller, als gesammelt wird, steht das Spiel am Ende trotzdem auf einen Schlag still. Auch die Unreal Engine hat eine eigene GC, die nicht mehr genutzte Spielobjekte aufräumt. Abhängig von Engine-Version und Einstellungen läuft sie in der Standardkonfiguration etwa einmal pro Minute und kann so ein Stocken im Minutentakt verursachen. Clients, deren Spielregeln in einer Skriptsprache wie Lua geschrieben sind, haben zusätzlich die eigene GC dieser Skriptsprache.
Quellen
Garbage collection modesUnity Inkrementelle GC ist Standard und sammelt verteilt über mehrere Frames. Ohne sie steht der Main-Thread still, während der gesamte Heap durchsucht wird, im Extremfall mehrere hundert ms
Profiler markers referenceUnity GC.Collect: Abschnitt, in dem der Programmcode während der Garbage Collection angehalten ist (unter 1 ms bis mehrere hundert ms), GC.Alloc: Allokation im Managed Heap
Stat Commands in Unreal EngineEpic Games stat GC (Statistik zur Garbage Collection), stat Hitches (protokolliert Frames über t.HitchFrameTimeThreshold)