Zielmarkierungen werden in vielen Spielen verwendet, um einen Spieler zum nächsten Ziel oder zu einem interessanten Punkt zu führen. In diesem Tutorial lernst du, wie du mit dem Kartenkennzeichner-Gerät und Verse eine wiederverwendbare Zielmarkierung erstellen kannst.
Verwendete Sprachfunktionen in Verse
struct: Du kannst variables von unterschiedlichen types in einem struct gruppieren.
Extension method: Eine spezielle Art von function, die sich wie ein Member einer bestehenden class oder eines Typs verhält, aber nicht die Erstellung eines neuen Typs oder eine subclass erfordert. In dieser Anleitung erstellst du eine Erweiterungs-method für die Struktur.
named argument: Ein argument das an einen function call mit seinem parameter übergeben wird.
Verwendete APIs in Verse
creative_prop API: Die
creative_prop-API bietet Methoden für die Bewegung von Props.Editable Properties: Mehrere Eigenschaften werden verwendet, um sowohl Geräte zu verweisenn als auch variable values für schnelle Tests zu aktualisieren.
Anweisungen
In den folgenden Schritten lernst du, wie du ein einzelnes Zielmarkierungsgerät einrichtest, das sich zu mehreren Zielen oder Interessenpunkten bewegen kann. Die vollständigen Scripts sind am Ende dieses Leitfadens als Referenz enthalten.
Level einrichten
Dieses Beispiel verwendet die folgenden Props und Geräte.
1 x Gebäude-Prop: Ein Prop, das verwendet wird, um das Kartenkennzeichner-Gerät zu verschieben.
1 x Kartenkennzeichner-Gerät: Ein Gerät, das benutzerdefinierte Markierungen auf der Minimap und der Übersichtskarte anzeigt.
1 x Spieler-Spawnfläche-Gerät: Füge dies in der Nähe des Props hinzu, sodass der Spieler in dessen Nähe spawnen kann.
Verwendung der Prop-API
Der erste Schritt, um ein Gerät mit Verse zu bewegen, ist das Bewegen eines Props mit der Prop API. Befolge diese Schritte, um ein Prop in deinem Level zu bewegen.
Erstelle ein neues Verse-Gerät mit dem Namen objective_coordinator_device.
Füge unter den standardmäßigen
using-Ausdrücken oben in der Verse-Datei einenusing-Ausdruck für das SpatialMath module hinzu. Dieses Modul enthält Code, den du zum Verschieben von Props verwenden wirst.Verseusing { /UnrealEngine.com/Temporary/SpatialMath }Füge zwei bearbeitbare Eigenschaften hinzu:
Eine
creative_prop-Konstante mit dem NamenRootPropzum Speichern eines Verweises auf das bewegliche Prop.Eine
transformKonstante mit dem NamenDestinationzum Speichern des Speicherorts, zu dem sich das Prop bewegen soll.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
Wenn du diesen Code ausführst und dein objective_coordinator_device in deinen Level ziehst, wirst du die beiden Eigenschaften im Panel Details sehen.
Die Methode
TeleportTo[]ist die eigentliche Bewegung des Props. Rufe es innerhalb einer if-expression auf und verwende square brackets anstelle von runden Klammern, weilTeleportTo[]ein fehlbarer Ausdruck ist. Dasiferzeugt einen failure context.Verseif(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Prop move successful") else: Print("Prop move failed")Die Argumente für
TeleportTo[]sind Übersetzung und Rotation. Beide stammen von deiner Ziel-Eigenschaft.Zurück im Editor ziehe ein Prop aus Fortnite > Galerien > Props in den Inhaltsbrowser. Die in dieser Anleitung verwendete heißt Küstenboje 02B, aber alles aus dem Ordner Props sollte funktionieren.
Wähle dein Zielkoordinationsgerät im Outliner aus. Setze im Panel Details das RootProp auf dein Prop. In diesem Beispiel ist RootProp auf Coastal Buoy 02B gesetzt.
Erweitere im Panel Details das Ziel. Da Ziel vom Typ
transformist, besteht es aus Maßstab, Drehung und Verschiebung. Um das Prop zu bewegen, musst du nur die Verschiebung ändern, also erweitere das. Setze das Feld, das mit X endet, auf 5000,0.Beim Testen von Code ist es ratsam, große Änderungen an Werten vorzunehmen, damit die Auswirkungen offensichtlich sind. Kleine Änderungen können es schwierig machen, zu erkennen, ob dein Code das tut, was du erwartest.
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} # Where the marker will be moved toKlicke auf Verse, dann auf Verse-Code erstellen, und dann auf Sitzung starten. Klicke zum Schluss auf Spiel starten. Du solltest sehen, wie sich dein Prop bewegt.
Parent und Strukturen
Du hast jetzt ein Prop, das sich in deinem Level bewegt, aber das eigentliche Ziel ist es, ein Kartenkennzeichner-Gerät zu bewegen, damit die Spieler es als Wegpunkt verwenden können. Folge diesen Schritten, um ein Gebäude-Prop- und Kartenkennzeichner-Gerät zu deinem Level hinzuzufügen und es am Prop zu befestigen.
Klicke mit der rechten Maustaste in den Inhaltsbrowser, um das Kontextmenü zu öffnen.
Wähle Blueprint-Klasse aus dem Kontextmenü.
Klicke im Fenster Parent-Klasse auswählen auf Gebäude-Prop.
Eine neue Blueprint-Klasse erscheint in deinem Inhaltsbrowser. Bennen sie um in BuildingProp
Ziehe das Gebäude-Prop in dein Level. Dieses Prop hat kein Mesh, daher siehst du nur sein Transformations-Gizmo.
Ziehe im Outliner das Kartenkennzeichner-Gerät auf das Prop. Dadurch wird das Gebäude-Prop zum Parent-Gerät des Kartenkennzeichner-Geräts. Wenn sich nun das Gebäude-Prop bewegt, bewegt sich das Kartenkennzeichner-Gerät mit ihm.
Du weißt bereits, wie man ein Gerät mit Verse erstellt, aber du kannst auch Verse-Dateien erstellen, die keine eigenen Geräte haben.
Erstelle eine neue Verse-Datei und nenne sie objective_marker. Diese Datei erstellt kein Gerät. Stattdessen wird sie die Definition eines
structenthalten, das dem zuvor erstellten Verse-Gerät ausgesetzt werden soll.Beginne mit der Deklaration einer
Strukturmit dem Namen objective_marker. Sie hat zwei Mitglieder:RootPropundMapIndicator. Beide sollten den Bezeichner@editablehaben.Verseobjective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
Erweiterungsmethoden und benannte Argumente
Declare eine einzelne Methode, MoveMarker, die das RootProp-Mitglied und das damit verbundene Kartenkennzeichner-Gerät verschiebt. Mit dieser Methode werden zwei Sprachmerkmale eingeführt: Erweiterungsmethoden und benannte Argumente.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =Erweiterungsmethoden: Du fügst die Methode
MoveMarker()zur Strukturobjective_markerhinzu. Eine Erweiterungsmethode wird durch Klammern deklariert, die eine Kennung und einen Typ umgeben, die durch einen Doppelpunkt getrennt sind. In diesem Fall:(Marker : objective_marker).Benannte Argumente: Das zweite Argument
?OverTimeverwendet das?, um anzuzeigen, dass es im FunktionsaufrufMoveMarkerbenannt werden muss. Das hilft jedem Entwickler, der einen Aufruf vonMoveMarkerliest oder schreibt, zu verstehen, was das Argumentfloatbewirkt.
MoveMarker() ruft eine von zwei Methoden aus der Prop-API auf: TeleportTo[], die du bereits benutzt hast, oder MoveTo(). Erstelle einen if..else-Block, um zu testen, ob der Parameter OverTime größer als 0,0 ist. Ist dies der Fall, rufe MoveTo() auf. Dadurch wird dein Ziel über eine von dir festgelegte Zeitspanne an seinen nächsten Standort bewegt, anstatt sich sofort zu teleportieren.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]Wenn du den Code jetzt kompilierst, sollte er erfolgreich sein, aber du solltest kein neues Gerät im Ordner CreativeDevices im Inhaltsbrowser sehen. Das liegt daran, dass objective_marker eine struct ist, keine Klasse, die von creative_device übernimmt.
Aktualisierung des Zielkoordinatorgeräts
Da Sie nun einen neuen Typ haben, auf den Sie verweisen können, müssen Sie das objective_coordinator_device aktualisieren, um darauf zu verweisen.
Lösche die Eigenschaft
RootPropund ersetze sie durch eine Eigenschaft mit dem NamenPickupMarkervom Typobjective_marker. Dies ist der von dir erstellte Typ.MoveMarker()erfordert ein Argument vom Typfloat, das als bearbeitbare Eigenschaft mit dem NamenMoveTimeerstellt wird.Lösche den Aufruf von
TeleportTo[]. Rufe stattdessen die MethodeMoveMarker()auf, die du fürobjective_markererstellt hast. Es erfordert das Argument mit dem Namen?OverTime.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{} # How much time the marker should take to reach its new location
Kompiliere diesen Code und überprüfe die Details des Zielkoordinators. Du solltest die Eigenschaften PickupMarker und MoveTime sehen, und PickupMarker sollte RootProp und MapIndicator enthalten.
Setze das Feld RootProp auf BuildingProp, und das Feld MapIndicator auf das Kartenkennzeichnergerät.
Kompiliere deinen Code und klicke auf Sitzung starten. Du solltest eine Markierung auf deiner Minikarte sehen, die sich kurz nach deinem Spielstart bewegt. Probiere verschiedene Werte für
MoveTimeaus, einschließlich0.0. Überlege dir, welche Bewegung für die verschiedenen Szenarien am besten geeignet ist.
GetPlayers() und ActivateObjectivePulse()
Es gibt eine Möglichkeit, deinen Spielern auf dem Weg zum nächsten Ziel ein wenig zu helfen. Er wird als Zielimpuls bezeichnet und zeigt, wenn er aktiv ist, eine gepunktete Linie, die sich vom Spieler zum Kartenkennzeichner-Gerät bewegt. Folge den nachstehenden Anweisungen, um einen Zielimpuls zu deinem Zielkoordinator hinzuzufügen.
Die Methode zur Aktivierung des Zielimpuls heißt ActivateObjectivePulse() und erfordert ein Argument vom Typ agent. Beginne mit der Erstellung der Methode, um die Instanz von agent zu erhalten, die deinen Spielcharakter darstellt.
Deklariere eine Funktion mit dem Namen
FindPlayer(), die auf<private>gesetzt ist, mit einem Rückgabewert vonvoid.Erhalte ein Array mit allen Spielern in deinem Level mit
Self.GetPlayspace().GetPlayers(). Speichere das Array in einer Variablen mit dem NamenAllPlayers.VerseFindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()Um den Verweis auf den einzigen Spieler in deinem Level zu erhalten, weise das erste Array-Element seiner eigenen Variablen zu. Der Zugang zu einem Array ist eine failable expression, also platziere ihn in einem
if-Ausdruck.Verseif (FirstPlayer := AllPlayers[0]):Da die Zuweisung deines
playerzu einer Variablen fehlschlagen könnte, solltest du eine Variable vom Typ option verwenden, wenn du in deinem Code auf den Spieler verweist. Deklariere eine optionale Spielervariable?player. Sie sollte zu den anderen Mitgliedsvariablen passen.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{}Setze deine neue Variable und erstelle einen
else-Block mit einemPrint()-Ausdruck, der dir mitteilt, wenn ein Spieler nicht gefunden wurde. Deine FunktionFindPlayer()ist nun vollständig.VerseFindPlayer<private>() : void = # Since this is a single player experience, the first player [0] # should be the only one available. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Player found")
Zurück in der Funktion OnBegin() musst du zwei weitere Änderungen vornehmen:
Rufe deine Funktion
FindPlayer()auf.VerseOnBegin<override>()<suspends> : void = FindPlayer()Verwende nach dem Aufruf von
MoveMarker()einen weiterenif-Ausdruck, um deine optionale Spielervariable auf eine neue Variable zu setzen, und übergebe diese als Argument anPickupMarker.MapIndicator.ActivateObjectivePulse()Verseif (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Wenn du deinen Code jetzt ausführst, solltest du sehen, dass der Zielimpuls von deinem Charakter auf die Position der Zielmarkierung im Level zeigt!
Vollständige Scripts
Objective_marker.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Devices/CreativeAnimation }
objective_marker<public> := struct<concrete>:
# The prop that will be moved
@editable
RootProp<public> : creative_prop = creative_prop{}
Objective_coordinator_device.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Playspaces }
using { /UnrealEngine.com/Temporary/SpatialMath }
objective_coordinator_device<public> := class<concrete>(creative_device):
var PlayerOpt<private> : ?player = false
@editable
Du bist am Zug
Denke daran, dass der Bewegungscode, den du hier geschrieben hast, für jedes Prop funktioniert. Wenn du ein bewegliches Prop einem Gerät überordnen kannst, bewegt sich das Gerät mit ihm. Versuche, andere Props und Geräte zu verschieben, und überlege, ob dir andere Spiele einfallen, bei denen sie verwendet werden könnten.
Nächste Schritte
Wenn du diese Anleitung verwendest, um das Abhol-/Lieferspiel zu programmieren, solltest du als Nächstes lernen, die Countdown-Timer-Funktion zu erstellen.