UE5Coro implementiert C++20-Coroutine-Unterstützung für Unreal Engine 5 mit Schwerpunkt auf Gameplay-Logik, Komfort und der Bereitstellung einer nahtlosen Integration mit der Engine.
Notiz
Unterstützung für C++17, ältere Compiler, Plattformen und Engine-Versionen ist in der älteren UE5Coro 1.x-Serie verfügbar.
Es gibt integrierte Unterstützung für die einfache Erstellung latenter UFUNCTIONs. Ändern Sie den Rückgabetyp einer latenten UFUNCTION, um daraus eine Coroutine zu machen, und Sie erhalten das gesamte FPendingLatentAction-Boilerplate kostenlos, mit BP-sicherer Multithreading-Unterstützung sofort einsatzbereit:
UFUNCTION (BlueprintCallable, meta = (Latent, LatentInfo = LatentInfo))
FVoidCoroutine Example(FLatentActionInfo LatentInfo)
{
UE_LOGFMT (LogTemp, Display, " Started " );
co_await UE5Coro::Latent::Seconds ( 1 ); // Does not block the game thread!
UE_LOGFMT (LogTemp, Display, " Done " );
co_await UE5Coro::Async::MoveToThread (ENamedThreads::AnyThread);
auto Value = HeavyComputation ();
co_await UE5Coro::Async::MoveToGameThread ();
UseComputedValue (Value);
}
Diese Coroutine verfolgt ihr Ziel-UObject automatisch über Threads hinweg. Selbst wenn ihr besitzendes Objekt zerstört wird, bevor es fertig ist, stürzt es nicht ab, weil this
im Spiel-Thread baumelt.
Sogar der Coroutine-Rückgabetyp ist vor BP verborgen, um Designer nicht zu stören:
Kein Interesse an latenten UFUNKTIONEN? Kein Problem. Es werden auch rohe C++-Coroutinen mit genau demselben Funktionsumfang unterstützt. Die unterstützende Implementierung wird zur Kompilierzeit ausgewählt; Latente Aktionen werden nur erstellt, wenn Sie sie tatsächlich verwenden.
Ändern Sie Ihren Rückgabetyp in einen der von diesem Plugin bereitgestellten Coroutine-Typen, und komplexe asynchrone Aufgaben, deren Implementierung mühsam wäre, werden zu trivialen Einzeilern, die einfach funktionieren, sodass Rückrufe und andere Handler nicht mehr erforderlich sind.
UObject* HardPtr = co_await AsyncLoadObject(SoftPtr);
ermöglicht es Ihnen, nur die Vorteile (und Ihre FPS) zu behalten.co_await NextTick();
innerhalb einer Schleife, und schon sind Sie fertig. Es gibt eine Zeitbudgetklasse, mit der Sie die gewünschte Verarbeitungszeit direkt angeben und die Coroutine dynamisch selbst planen lassen können.co_await Ticks(bCloseToCamera ? 1 : 2);
co_await MoveToTask();
hinzufügen zu Ihrer Funktion hinzufügen, und alles nach dieser Zeile wird innerhalb des UE::Tasks-Systems in einem Arbeitsthread ausgeführt.co_await MoveToGameThread();
.co_await Timeline(this, From, To, Duration, YourUpdateLambdaGoesHere);
co_await YourDynamicDelegate;
(das ist der gesamte Code)auto [Your, Parameters] = co_await YourDynamicDelegate;
Dies soll einen Vorgeschmack auf die erhebliche Reduzierung von Code und Aufwand geben, die mit diesem Plugin möglich ist. Weniger und einfacher zu schreibender Code führt im Allgemeinen zu weniger Fehlern, und da asynchroner Code einfach zu schreiben ist, gibt es keine Reibungsverluste, wenn es darum geht, die Dinge sofort richtig zu machen.
Verabschieden Sie sich von dem Good-enough-for-now™ LoadSynchronous, das sich zwei Updates später noch im Versand befindet. Wenn die anstehende Aufgabe von „Schreiben Sie das gesamte StreamableManager-Boilerplate und verschieben Sie einen Teil der aufrufenden Funktion in einen Rückruf“ auf lediglich „co_await davor kleben“ reduziert wird, sind Sie schneller fertig, als es nötig gewesen wäre mit einer Begründung, warum die synchrone Blockierungsversion irgendwie akzeptabel ist.
Es gibt viele zusätzliche Funktionen im Plugin, wie zum Beispiel Generatoren, mit denen Sie vermeiden können, ein ganzes TArray zuzuweisen, nur um eine variable Anzahl von Werten zurückzugeben. Einfacher für Sie zu schreiben, einfacher für den Compiler zu optimieren, Sie benötigen nur O(1)-Speicher anstelle von O(N) für N Elemente, was gibt es daran nicht zu mögen?
Über die folgenden Links gelangen Sie zu den entsprechenden Seiten der Dokumentation. Setzen Sie ein Lesezeichen für diesen Abschnitt, wenn Sie die neueste Dokumentation lieber in Ihrem Browser oder direkt von Ihrer IDE aus lesen möchten. Jede API-Funktion ist in den C++-Headern dokumentiert und die Releases enthalten die Markdown-Quelle der Dokumentation, die Sie gerade lesen.
Diese Funktionen konzentrieren sich darauf, Coroutinen dem Rest der Engine zugänglich zu machen.
Diese Wrapper bieten praktische Möglichkeiten, Engine-Funktionen aus Ihren Coroutinen zu nutzen.
Notiz
Die meisten dieser Funktionen geben undokumentierte interne Typen aus dem UE5Coro::Private
-Namespace zurück. Der Clientcode sollte nicht direkt auf etwas aus diesem Namespace verweisen, da alles darin in zukünftigen Versionen ohne vorherige Ablehnung geändert werden kann.
In den meisten Fällen stellt dies kein Problem dar: Beispielsweise erscheint das unbenannte temporäre Objekt in co_await Something()
nicht im Quellcode. Wenn ein Private
Rückgabewert gespeichert werden muss, verwenden Sie auto
(oder ein eingeschränktes TAwaitable auto
), um das Schreiben des Typnamens zu vermeiden.
Der direkte Aufruf der öffentlichen C++-erwartbaren C++-Funktionen „ await_ready
, await_suspend
und await_resume
wird auf keinem Awaiter unterstützt.
Es werden nur nummerierte Veröffentlichungen unterstützt. Verwenden Sie die Git-Zweige nicht direkt.
Laden Sie die von Ihnen ausgewählte Version herunter und extrahieren Sie sie in den Plugins-Ordner Ihres Projekts. Benennen Sie den Ordner einfach in UE5Coro um, ohne Versionsnummer. Wenn Sie es richtig machen, sollten Sie am Ende YourProjectPluginsUE5CoroUE5Coro.uplugin
erhalten.
Notiz
Bitte lesen Sie die README-Datei der Version, wenn Sie 1.x verwenden. Es gab eine andere Installationsmethode mit mehreren Plugins.
Ihr Projekt verwendet möglicherweise einige Legacy-Einstellungen, die entfernt werden müssen, um die C++20-Unterstützung freizuschalten, die ansonsten in neuen Projekten, die in Unreal Engine 5.3 oder höher erstellt wurden, zum Standard gehört.
Stellen Sie in Ihren Target.cs- Dateien (in allen) sicher, dass Sie die neuesten Einstellungen verwenden und die Bestellversion angeben:
DefaultBuildSettings = BuildSettingsVersion . Latest ;
IncludeOrderVersion = EngineIncludeOrderVersion . Latest ;
Wenn Sie das alte bEnableCppCoroutinesForEvaluation
-Flag verwenden, ist dies nicht mehr erforderlich und sollte nicht mehr explizit aktiviert werden. Dies kann zu Problemen führen. Es wird empfohlen, alle Verweise darauf aus Ihren Build-Dateien zu entfernen.
Wenn Sie CppStandard
in einer Build.cs-Datei auf CppStandardVersion.Cpp17
setzen ... tun Sie das nicht :)
Verweisen Sie auf das Modul "UE5Coro"
aus Ihrer Build.cs wie auf jedes andere C++-Modul und verwenden Sie #include "UE5Coro.h"
. Das Plugin selbst muss nicht aktiviert werden.
Einige Funktionen sind in optionalen Modulen enthalten, auf die separat verwiesen werden muss. Beispielsweise benötigt die Unterstützung des Gameplay Ability Systems "UE5CoroGAS"
in Build.cs und #include "UE5CoroGAS.h"
. Das UE5Coro-Kernmodul hängt nur von Engine-Modulen ab, die standardmäßig aktiviert sind.
Wichtig
Fügen Sie keinen anderen Header direkt mit #include ein, sondern nur den, der mit dem Modulnamen übereinstimmt. Es ist bekannt, dass große IDEs, die mit der Unreal Engine verwendet werden, falsche Header-Vorschläge erhalten. Wenn Sie UE5Coro.h zu Ihrem PCH hinzufügen, können Sie es überall verfügbar machen.
Löschen Sie zum Aktualisieren UE5Coro aus dem Plugins-Ordner Ihres Projekts und installieren Sie die neue Version gemäß den obigen Anweisungen.
Das separate Packen von UE5Coro (über das Plugins-Fenster) ist nicht erforderlich und wird nicht unterstützt.
Um das Plugin aus Ihrem Projekt zu entfernen, implementieren Sie alle Ihre Coroutinen ohne seine Funktionalität erneut, entfernen Sie alle Verweise auf das Plugin und seine Module und fügen Sie eine Kernumleitung von /Script/UE5CoroK2.K2Node_UE5CoroCallCoroutine
zu /Script/BlueprintGraph.K2Node_CallFunction
hinzu.