Was sind die Teile eines Charakters in der Unreal Engine?
Wie im Abschnitt Spielmodus/Spielstatus erwähnt, hilft das Unreal-Engine-Gameplay-Framework dabei zu verstehen, wie Charaktere in der Unreal Engine funktionieren. Konzeptionell besteht ein Spieler aus einem Pawn, der die physische Präsenz in der Spielwelt repräsentiert, und einem Controller, der das Verhalten steuert. Diese Entkopplung ist sowohl für KI als auch für die Netzwerkreplikation nützlich. Zur Referenz – die Hierarchie sieht wie folgt aus:
Beginnen wir mit dem Importieren der Assets, dem Erstellen des Pawns und der Arbeit bis zum Player-Controller. Für „Parrot“ wird unser vom Spieler gesteuerter Held Kapitän Barbarossa sein (besuche die Webseite von Quaternius, um das von Quaternius bereitgestellte Piraten-Kit abzurufen).
Importieren von Art-Assets
Exportiere deine Meshs/Animationen in einem 3D-Modellierungswerkzeug deiner Wahl in ein Engine-kompatibles Format. In diesem Fall haben die Entwickler .fbx verwendet. Die Assets von Barbarossa findest du unter Content/Assets/Quaternius/PirateKit/Characters/Barbarossa. Du kannst deine .fbx importieren, indem du mit der rechten Maustaste auf das Kontextmenü klickst oder es in den Inhaltsbrowser ziehst und dort loslässt. Du siehst dann ein Fenster für die Importeinstellungen der . fbx- Datei. Wähle die entsprechenden Optionen für deinen Importer. Vergewissere dich in diesem Fall, dass kein vorhandenes Skelett ausgewählt ist und dass Animationen importieren mit einem Häkchen versehen ist. Außerdem musst du ein neues Atlas-Material erstellen, das von deinem Mesh indiziert werden kann. Dieses Material kann in allen Assets des Piraten-Kits wiederverwendet werden. Nun sollten diese 3 Dateien und alle Animationen in deine .fbx-Datei eingebunden sein.
Der Ordnung halber befinden sich die Dateien der Animationssequenz unterhalb des Ordners Animations neben den 3 Dateien:
Skelett, Skelett-Mesh und Physik-Assets
Ein Skelett ist eine Hierarchie, die dazu verwendet wird, Bones (manchmal auch Gelenke genannt) in einem Skelett-Mesh zu definieren. Diese Bones sollten mit dem Rig in deinem 3D-Modellierungswerkzeug übereinstimmen. Skelette können über Skelett-Meshs hinweg wiederverwendet werden, solange die Rigs kompatibel sind. Du wirst auch ein erstelltes Physik-Asset sehen. Physik-Assets definieren die Physik und Kollision, die von einem Skelett-Mesh verwendet werden. Sie enthalten Festkörper und Beschränkungen für die Simulation. Du kannst nur ein Physik-Asset pro Skelett-Mesh haben und diese können bedingt ein- oder ausgeschaltet werden. Du kannst Physik-Assets anpassen, wenn sie importiert werden, oder neue Assets aus einem Skelett-Mesh erstellen.
Animationsblueprint
Jetzt, wo du mit einem Skelett-Mesh arbeiten kannst, kannst du es mit dem Animation Blueprint animieren. Der Animation-Blueprint ist ähnlich wie das Mecanim Animation System von Unity. Das Animationsdiagramm in Animation-Blueprints sollte dir bekannt vorkommen und in ähnlicher Weise funktionieren. Beide Systeme verfügen über eine bedingte Logik, die einen Übergang der Animationszustände zu einer endgültigen Output-Pose ermöglicht. Erstelle über das Kontextmenü in deinem Ordner einen neuen Animationsblueprint und wähle dein Skelett aus. Unser Animationsblueprint wird ABP_Captain_Barbarossa heißen unter Content/Blueprints/Player.
Auf der linken Seite des Blueprint-Inspektors wirst du feststellen, dass es zwei Diagramme gibt: Event Graph und Animation Graph. Das Animationsdiagramm ist die Zustandsmaschine, die deine endgültige Output-Pose steuert. Im Event Graph kannst du jede Logik im Zusammenhang mit der Animation definieren. Im Gegensatz zu Unity, wo du Daten an die Mecanim-Komponente weitergeben musst, können Animationsblueprints bei einem bestimmten Event die benötigten Daten abrufen. Zum Beispiel möchtest du vielleicht die Geschwindigkeit des Charakters abfragen und deine Animation auf der Grundlage dieses Wertes erstellen. Eine praktische Möglichkeit, dies zu tun, besteht darin, den Event Blueprint Initialize Animation-Knoten im Event Graph zu verwenden, den besitzenden Actor abzurufen und seine Bewegungskomponente in einer Variablen zwischenzuspeichern. Von dort aus kannst du bei jedem Zähler von BlueprintThreadSafeUpdateAnimation die Geschwindigkeit direkt von deiner Bewegungskomponente aus abfragen. Variablen können auch zwischen dem Event Graph und dem Animationsdiagramm ausgetauscht werden.
Der konfigurierte Animationsblueprint für Barbarossa ist es wert, auf eigene Faust weiter erkundet zu werden. Wenn du auf die Knoten doppelklickst, kannst du sehen, wie die Zustandsmaschinen, Zustände und Zustandsregeln für die endgültige Output-Pose konfiguriert sind. Es gibt auch Beispiele für die Verwendung eines Sequenz-Players und die Verwendung eines Blendspace. In ähnlicher Weise zeigt der Event Graph, wie die Animation durch Charakterdaten angetrieben wird – diese Beziehung wird im weiteren Verlauf dieses Artikels noch deutlicher.
Pawn
Da es nun ein Skelett-Mesh gibt, das animiert werden kann, kannst du damit beginnen, deinen Pawn zu erstellen, der vom Spielmodus verwendet wird. Die Entwickler haben sich dafür entschieden, auf den Standard-Character der Unreal Engine aufzubauen, der eine Child-Klasse der Standard-Pawn-C++-Klasse ist. Die Character-Klasse hat eine Charakterbewegung-Komponente, die für dieses Spiel besonders nützlich ist und eine weitere Klasse ist, auf der du aufbauen kannst.
Sowohl der Spieler als auch die gegnerischen Pawns haben einige gemeinsame Funktionen wie Trefferpunkte, getroffen werden und Tod. Diese Funktionalität wird gemeinsam genutzt, indem eine C++-Klasse AParrotCharacterBase erstellt wird, die von ACharacter erbt. Diese Klasse bietet eine gute Ausgangsbasis, auf der du aufbauen kannst, da das Verhalten von gegnerischen und Spieler-Pawns unterschiedlich ist.
Als nächstes erstellst du einen AParrotPlayerCharacter in C++, um die spielerspezifische Logik zu handhaben. Zu guter Letzt erstellst du einen Blueprint, um die visuelle Darstellung deines Charakters zu handhaben. Der Blueprint von „Parrot“ ist BP_ParrotPlayerCharacter unter Content/Blueprints/Player. Die Vererbungshierarchie sieht wie folgt aus:
Wenn du BP_ParrotPlayerCharacter öffnest, solltest du einige Komponenten unter dem Komponenteninspektor auf der linken Seite des Editor-Fensters sehen. In der Mesh-Komponente kannst du dein Skelett-Mesh-Asset sowie den Animationsblueprint unter Anim Class einstellen. Wenn das Mesh nicht richtig positioniert ist, kannst du die Werte für die Transformation anpassen, um es an deiner Kapselkomponente auszurichten. Du solltest so etwas wie das hier haben:
Als nächstes kannst du dem Blueprint im Spielmodus-Asset die Standard-Pawn-Klasse zuweisen.
Jetzt gibt es einen animierenden Pawn, den du im Spiel verwenden kannst!
Player-Controller
Mit einem verwendbaren Pawn kannst du nun den Player-Controller erstellen. Player-Controller repräsentieren im Wesentlichen den Willen des menschlichen Spielers. Wenn du dein Spiel entwickelst, solltest du überlegen, wo du Input-Events definierst. Für einfache Spiele, bei denen sich die Pawns nicht verändern, ist der Pawn geeignet. Wenn das Verhalten jedoch beginnt, komplexer zu werden, ist der Player-Controller die bessere Option dafür. Pawns sind vorübergehend und können von Player-Controllern in Besitz genommen bzw. nicht in Besitz genommen werden. Pawns können gespawnt oder zerstört werden, während Player-Controller dauerhaft im Spiel verbleiben.
Du brauchst keine C++-Logik im Player-Controller, also erstell einfach einen Blueprint, der das tut, was nötig ist. BP_ParrotPlayerController befindet sich unter Content/Blueprints/Player. Die Vererbungshierarchie sieht wie folgt aus:
Innerhalb des Blueprints gibt es Input-Event-Knoten, die zu einer grundlegenden Logik im Gameplay führen. Diese Input-Events beziehen sich speziell auf den Enhanced Input. Mehr darüber, wie dies konfiguriert wird, erfährst du in der Dokumentation Enhanced Input. Wenn du den Spieler-Charakter-Pawn von „Parrot“ zu Beginn des Spiels zwischengespeichert hast, kannst du diese Funktion verwenden, um später die Basisfunktionen für die Bewegung aufzurufen. Zum Beispiel Bewegungs-Input hinzufügen, Springen und Springen beenden.
Zeit zum Testen! Stelle im Spielmodus-BP die neue Klasse des Player-Controllers ein und überprüfe dann, ob du den Controller im Spiel verwenden kannst:
Überprüfe anhand dieses Dropdowns im Level-Editor, ob der richtige Spielmodus ausgewählt ist:
Stelle abschließend sicher, dass deine Karte einen PlayerStart-Actor und eine Kamera hat, die du sehen kannst. Wenn du auf die Schaltfläche „Spielen“ klickst, solltest du sehen, wie sich dein Charakter bewegt und animiert wird:
Charakter-Bewegungskomponente in „Parrot“
Die Basis-Klasse ACharacter hat eine Menge großartiger Funktionen eingebaut. Ein Beispiel hierfür ist die UCharacterMovement-Actor-Komponente. Die Charakter-Bewegungskomponente handhabt die gesamte Logik dafür, wie ein Charakter sich durch die Welt bewegt. Sie unterstützt Gehen, Laufen, Fallen, Schwimmen, Fliegen und benutzerdefinierte Bewegungsmodi. Es lohnt sich auf jeden Fall, auf eigene Faust zu erkunden, um eine Vorstellung davon zu bekommen, wie die grundlegende Bewegung eines Charakters funktioniert und um eine Vorstellung davon zu bekommen, wie mächtig die Actor-Komponenten sind.
Bei „Parrot“ bot die Basis-Charakter-Bewegungskomponente nicht das Spielgefühl, das sich die Entwickler erhofft hatten. Aber es war eine solide Grundlage, auf der wir aufbauen konnten. Die C++-Klasse UParrotCharacterMovementComponent ist eine Ableitung von UCharacterMovementComponent. Wir können dann die Bewegungskomponente auf der CDO-Bewegungskomponente in BP_ParrotPlayerCharacter wie folgt einstellen:
Aber was macht die Bewegungskomponente in „Parrot“ eigentlich? Im Wesentlichen erlaubt dir die Komponente, einen Sprung im „Platformer-Stil“ zu definieren, indem du Funktionen aus der Basis-Bewegungskomponente, die sich auf das Springen beziehen, außer Kraft setzt. Wenn du einige im Design einstellbare Werte verwendest, kannst du bei einem Sprung die Skalierung der Schwerkraft und die Geschwindigkeit des Spieler-Charakters so verändern, dass er die Scheitelhöhe in einer festgelegten Zeit erreicht. Wenn du den Scheitelpunkt erreicht hast, kannst du beginnen, eine fallende Schwerkraftskalierung anzuwenden. Wenn der Spieler den Sprung-Input zu früh loslässt, kannst du einen Multiplikator anwenden, um die Schwerkraft zu erhöhen.
Das Ergebnis ist ein Sprung, der sich mehr wie ein Jump‘n‘Run anfühlt, als wenn du nur einen Impuls auf der Z-Achse anwenden würdest.
Da du dich auf die komplexe Logik der Basis-Charakter-Bewegungskomponente stützt, kannst du dich zum Springen ganz auf die Logik der „Parrot“-Bewegungskomponente konzentrieren. Die Werte im Inspektor für BP_ParrotPlayerCharacter auf der Bewegungskomponente sind ebenfalls einen Blick wert, um sich ein vollständiges Bild davon zu machen, wie alle Teile der Bewegungskomponente zusammenarbeiten. Die Logik der Bewegungen kann für eine Vielzahl von Anwendungszwecken erweitert werden.