Warum sollte ich immer in Betracht ziehen, Objektpools zu erstellen und zu verwenden, anstatt das neue Objekt sofort zu instanziieren?

25

Ich habe mehrmals über dieses Muster gelesen (aus der Perspektive der Best Practices):

Speicherzuweisung : Anstatt das neue Objekt sofort zu instanziieren, sollten Sie immer in Betracht ziehen, Objektpools zu erstellen und zu verwenden. Dies verringert die Fragmentierung des Arbeitsspeichers und verringert die Belastung des Garbage Collectors.

Ich weiß jedoch nicht, was es eigentlich bedeutet. Wie kann ich das umsetzen?

Zum Beispiel kann ich eine Instanz GameObjectmit der InstantiateMethode von Unity?

Instantiate(prefab, new Vector3(2.0F, 0, 0), Quaternion.identity);

Wird von dieser Verwendung abgeraten? Was kann es sonst noch bedeuten?

Muhammad Faizan Khan
quelle
Dank Hellium habe ich das gegebene Video (zu groß) nicht gesehen, aber der Text hilft mir wirklich zu verstehen, "Der Vorgang des Instanziierens und Zerstörens ist ineffizient und kann Ihre Projekte verlangsamen"
Muhammad Faizan Khan
1
Beachten Sie, dass dieser Rat zwar häufig verwendet wird, jedoch nicht für jedes Spiel zwingend erforderlich ist. Vor allem, wenn Sie ein kleines / kurzes Desktop-Spiel, einen Jam-Beitrag oder einen Prototyp erstellen, müssen Sie sich nicht viel Mühe geben, um das Pooling zu implementieren. In meinen Tränktests hält Unity sogar massivem Laichen und Zerstören besser stand, als wir es glauben. ;) Aber überlegen Sie sich einen Pool, wenn Sie ein langes Spiel machen, bei dem sich kein Müll ansammeln und ein Stottern verursachen soll, wenn er später gesammelt wird, oder wenn Sie auf mobile Plattformen abzielen, auf denen Leistungseinbußen deutlicher zu spüren sind.
DMGregory
Danke @DMGregory Du hast recht. Ihre Eingabe ist immer wertvoll. Wir sollten uns keine Gedanken über das Zusammenfassen von Objekten in kleinen Spielen machen, da dies zusätzliche Arbeit beim Codieren erfordert.
Muhammad Faizan Khan
1
Dies ist ein sehr verbreitetes Muster, aber achten Sie darauf, es mit der Regel zu temperieren: "Erst profilieren, dann optimieren." Es ist einfach, Dinge zu optimieren, die keine Rolle spielen.
Cort Ammon - Reinstate Monica

Antworten:

41

Wenn Sie vorhaben, viele Instanzen desselben Fertighauses zu instanziieren, sollten Sie auf jeden Fall über die Verwendung von Objektpooling nachdenken. Das Aufrufen der Instantiate-Funktion von Unity ist eine der anstrengendsten Methoden, die Sie durchführen können.

Objekt-Pooling ist, wenn Sie Fertigteile instanziieren, bevor sie verwendet werden. Sie werden sofort nach der Instantiierung deaktiviert und erst dann wieder aktiviert, wenn sie benötigt werden. Dies erhöht zwar die Speichernutzung, vermeidet jedoch den CPU-Overhead beim Instanziieren während des Spiels.

Zum Beispiel arbeite ich gerade an einem Bullet-Hell-Spiel, bei dem Hunderte von Kugeln zur Laufzeit erzeugt werden müssen. Ich habe anfangs versucht, das Spiel ohne Objekt-Pooling zu machen, aber das endete mit einer Katastrophe (weniger als 2 fps). Jetzt sammle ich 500 Kugeln, bevor das Spiel beginnt und das Spiel läuft erstaunlich schnell (200 fps).

Es gibt Situationen, in denen Objektpooling nicht verwendet werden kann. Wenn Sie beispielsweise ein Spiel haben, in dem die Eingaben des Spielers bestimmen, welche Fertigteile erzeugt werden, haben Sie möglicherweise keine andere Wahl, als den normalen Instantiate-Aufruf zu verwenden. Objekt-Pooling ist nur möglich, wenn Sie im Voraus wissen, welche Objekte benötigt werden.

Das YouTube-Tutorial von Sebastian Lague ist eine großartige Ressource, um mehr über das Pooling von Objekten zu erfahren: https://youtu.be/LhqP3EghQ-Q

Kevin H.
quelle
"Das Instanziieren und Zerstören ist ineffizient und kann Ihre Projekte verlangsamen." Das ist der Grund? Das bedeutet, dass wir etwas mehr Code benötigen (z. B. Deaktivieren aktivieren oder die Position der Kugel erneut festlegen, damit wir erneut feuern können)
Muhammad Faizan Khan
12
Es könnte erwähnenswert sein, die Zuordnung und die Speicherbereinigung als Hauptursachen für die Kosten der wiederholten Instanziierung und Zerstörung zu nennen. Generiere genug Müll und irgendwann muss das ganze Spiel darauf warten, dass der Müllsammler alles aufräumt. ;)
DMGregory
3
@ CorsiKa das wäre eine 80er Ära Optimierung. Unity kann die fraglichen Fertighäuser einfach deaktivieren, sodass ihre Systeme sie ignorieren.
Congusbongus
2
"Wenn Sie beispielsweise ein Spiel haben, in dem die Eingaben des Spielers bestimmen, welche Fertighäppchen erzeugt werden, haben Sie möglicherweise keine andere Wahl, als den normalen Instantiate-Aufruf zu verwenden." - Nicht wirklich. Sie können problemlos mehrere Objektpools für verschiedene Prefabs haben, die beim Start (oder beim Laden der Szene) den gewünschten Größen zugewiesen werden. Wenn man es machen möchte, könnte auch ein Objektpool funktionieren, in dem mehrere Fertigbautypen gespeichert sind.
Ethan Bierlein
1
@DMGregory In einer typischen GC-Umgebung macht die Aufhebung der Zuordnung den größten Teil der Kosten aus. In einer typischen Nicht-GC-Umgebung macht die Zuordnung den größten Teil der Kosten aus. Objekt-Pooling funktioniert für beide sehr gut, sie sind zum größten Teil nur zwei Seiten einer Medaille. Im Extremfall wurden alte Spiele mit allen Objekten geschrieben, die von Anfang an "zugewiesen" wurden - sehr wenig oder keine Speicherzuweisung, während das Spiel lief. Sie haben nicht wirklich etwas verwendet, das nicht in irgendeiner Weise "gepoolt" wurde. Da Unity viele "Metadaten" in Echtzeit verwendet, kann das Pooling sehr hilfreich sein - auch wenn es schwieriger zu implementieren ist.
Luaan