Es gibt verschiedene Möglichkeiten, wie du Props in UEFN verschieben kannst. Du kannst Funktionen wie TeleportTo[] oder MoveTo() nutzen, um eine Transformation direkt zu verändern, oder ein anderes Gerät wie einen Objektbeweger verwenden, um ein Prop entlang eines zuvor festgelegten Pfads zu verschieben. Animationen bieten eine weitere nützliche Option.
Jedes Kreativmodus-Prop verfügt über einen play_animation_controller, mit dem du Animationen davon wiedergeben kannst. Animationen haben gegenüber der Bewegung der Transformation eines Prop einige Vorteile. Animationen haben normalerweise eine glattere Bewegung als die Bewegung von Objekten mit MoveTo() oder TeleportTo(), da die Netzwerklatenz des Aufrufs dieser Funktionen bei jedem Spiel-Tick vermieden wird. Animationen verfügen außerdem über einheitlichere Kollisionen mit Spielern oder anderen Objekten und du hast im Vergleich zur Verwendung eines Objektbeweger-Geräts eine größere Kontrolle darüber, wo und wie sich Objekte bewegen. Du kannst Animationen in einer Schleife wiedergeben oder mit dem Ping-Pong-Modus vorwärts und rückwärts laufen lassen.
Du kannst mit Animationen außerdem einen Interpolationstyp auswählen. Der Interpolationstyp bestimmt den Abschwächungstyp bzw. die Animationskurve, der deine Animation folgt. Der lineare Interpolationstyp gibt deine Animation z. B. mit einer konstanten Geschwindigkeit wieder, während der Ease-in-Typ langsam startet und dann zum Ende hin an Geschwindigkeit aufnimmt. Durch die Auswahl des richtigen Interpolationstyps für deine Animation kannst du an verschiedenen Punkten festlegen, ob sich das Prop verlangsamen, beschleunigen oder sich linear bewegen soll.
Durch das Umschalten zwischen den verschiedenen Animationen für deine Hindernisse kannst du eine Vielzahl unterschiedlicher Herausforderungen für Spieler mit den gleichen Props erstellen. In diesem Abschnitt erfährst du, wie du dieses leistungsstarke Tool nutzen kannst, um eigene Animationen zu erstellen, damit sich deine Props bewegen.
Einrichten der Animationssteuerelemente
Folge den unten stehenden Schritten, um die Animationssteuerelemente für deine Props einzurichten:
Erstelle mit dem Verse-Explorer eine neue Verse-Datei mit dem Namen
movement_behaviors. Diese speichert die Hilfsfunktionen, die du für die Animation der Props benötigst.Füge die Anweisungen
using { /Fortnite.com/Devices },using { /Fortnite.com/Devices/CreativeAnimation }undusing { /UnrealEngine.com/Temporary/SpatialMath }oben in der Datei hinzu, um diese Module zu importieren. Du benötigst diese, um dein Prop zu animieren.Erstelle in
movement_behaviorseine neueEnummit der Bezeichnungmove_to_ease_type. Die Werte in dieser Enum entsprechen den verschiedenen Animationsabschwächungstypen. Du kannst jeden dieser Abschwächungstypen imInterpolationTypes-Modul anzeigen.Verse# This file stores functions common to animating creative props using keyframes. # It also defines the move_to_ease_type enum to help in building animations. using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } using { /Fortnite.com/Devices/CreativeAnimation } # Represents the different movement easing types. move_to_ease_type<public> := enum {Linear, Ease, EaseIn, EaseOut, EaseInOut}Füge einen neuen
vector3-Typ-Alias namensVectorOneshinzu, der einenvector3erstellt, bei demX,YundZalle auf1,0gesetzt sind. Dieser Vektor hilft dir später, einen Teil der Mathematik einfach zu machen. Wenn du also einen Typ-Alias erstellst, musst du nicht wiederholtvector3{X:=1.0, Y:=1.0, Z:=1.0}schreiben.Verse# Initializes a vector3 with all values set to 1.0. VectorOnes<public>:vector3 = vector3{X:=1.0, Y:=1.0, Z:=1.0}Füge eine neue
GetCubicBezierForEaseType()-Methode hinzu, die einenmove_to_ease_typeannimmt und einencubic_bezier_parameterszurückgibt.Verse# Return the cubic_bezier_parameters based on the given move_to_ease_type. GetCubicBezierForEaseType(EaseType:move_to_ease_type):cubic_bezier_parameters=Die kubische Bézierkurve besteht aus vier Zahlen, die den Typ der Abschwächungsfunktion definiert, die die Animation verwendet. Zum Beispiel verlangsamen die Parameter für eine Ease-in-Kurve die Animation zu Beginn und beschleunigen sie danach. Die Parameter für eine lineare Kurve geben die Animation mit einer konstanten Geschwindigkeit wieder. Du kannst diese Werte selbst definieren, um deine eigenen benutzerdefinierten Animationskurven zu erstellen. Aber in diesem Beispiel musst du das nicht, da du die verwendest, die im Modul
InterpolationTypesdefiniert wurden.Rufe in
GetCubicBezierForEaseType()in einemcase()-Ausdruck diecubic_bezier_parametersaus dem ModulInterpolationTypesbasierend auf demmove_to_ease_typeab. Zum Beispiel sollteEaseOutInterpolationTypes.EaseOutzurückgeben,LinearsollteInterpolationTypes.Linearzurückgeben und so weiter. Deine vollständigeGetCubicBezierForEaseType()-Funktion sollte wie folgt aussehen:Verse# Return the cubic_bezier_parameters based on the given move_to_ease_type. GetCubicBezierForEaseType(EaseType:move_to_ease_type):cubic_bezier_parameters= case (EaseType): move_to_ease_type.Linear => InterpolationTypes.Linear move_to_ease_type.Ease => InterpolationTypes.Ease move_to_ease_type.EaseIn => InterpolationTypes.EaseIn move_to_ease_type.EaseOut => InterpolationTypes.EaseOut move_to_ease_type.EaseInOut => InterpolationTypes.EaseInOutFüge zurück in deiner Klasse
movable_propeinen neuen bearbeitbarenmove_to_ease_typemit der BezeichnungMoveEaseTypehinzu. Dies ist der Abschwächungstyp, den dein Prop auf seine Animation anwendet.Verse# The type of animation easing to apply to the RootProp's movement. The easing type # changes the speed of the animation based on its animation curve. @editable {ToolTip := MoveEaseTypeTip} MoveEaseType:move_to_ease_type = move_to_ease_type.EaseInOut
Erstellen einer Animation mit Keyframes
Um Animationen im Code zu erstellen, verwendest du Keyframes. Animationen bestehen aus mindestens einem Keyframe und jeder Keyframe gibt die Werte eines Objekts an bestimmten Punkten in der Animation an. Durch das Erstellen einer Animation mit Keyframes kannst du mehrere Punkte festlegen, zu denen sich dein Prop bewegen, an denen es sich drehen oder sogar skalieren soll.
Keyframes haben fünf Werte. DeltaLocation, DeltaRotation und DeltaScale legen die Änderungen jedes Werts fest, die das Prop von Beginn bis Ende des Keyframe durchläuft. Es gibt auch Time bzw. die Zeit in Sekunden, die die Animation in Anspruch nimmt, und Interpolation bzw. der Interpolationsmodus für den Keyframe. Ein Beispiel-Keyframe könnte so aussehen:
# An example keyframe.
KeyFrame := keyframe_delta:
# The target position of the `creative_prop`. This is the difference between the starting and ending translation of the prop.
DeltaLocation := EndTransform.Translation - StartTransform.Translation,
# The target rotation for the `creative_prop` to rotate to.
DeltaRotation := EndTransform.Rotation,
# The target scale for the `creative_prop`. Scale is multiplicative to the starting Scale of the `creative_prop`
Befolge diese Schritte, um eine Animation mit Keyframes zu erstellen
Füge deiner
movement_behaviors-Datei eine neuecreative_prop-Erweiterungsmethode mit dem NamenMoveToEase()hinzu. Diese Funktion nimmt auch Position, Drehung und Skalierung für die Bewegung des Prop an, eine Dauer für den Ablauf der Animation, einen Bewegungsabschwächungstyp und einen Animationsmodus.Verse# Animate a creative_prop by constructing an animation from a single keyframe, and then playing that animation on the prop. # This method takes a Position, Rotation, and Scale for the prop to end at, the duration of the animation, # the type of easing to apply to the movement, and the animation mode of the animation. (CreativeProp:creative_prop).MoveToEase<public>(Position:vector3, Rotation:rotation, Scale:vector3, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void=Rufe in
MoveToEase()den Animationscontroller des Kreativmodus-Prop mitGetAnimationController[]ab. Der Animationscontroller lässt dich Animationen auf dem Prop wiedergeben und gibt außerdem ein Event frei, auf das du später warten wirst.Verse(CreativeProp:creative_prop).MoveToEase<public>(Position:vector3, Rotation:rotation, Scale:vector3, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void= # Get the animation controller for the CreativeProp to move. if (AnimController := CreativeProp.GetAnimationController[]):Berechne die Skalierungsänderung des Prop, die mit
ScaleMultiplicativebezeichnet wird.Scaleist in dieser Situation etwas komplexer. Da die Skalierung multiplikativ ist, muss die Skalierung der Endtransformation der Skalierung der ursprünglichen Transformation entsprechen, und nicht dem, auf was skaliert werden soll. Wenn z. B. die Skalierung der ursprünglichen Transformation1,2ist und du auf1,5skalieren möchtest, musst du tatsächlich um1,25skalieren, da1,2 * 1,25 = 1,5. Der endgültige Wert istVectorOnesplus die Differenz zwischen der neuen und alten Skalierung geteilt durch die alte Skalierung. Du benötigst diesen Wert, um sicherzustellen, dass deine Animation ordnungsgemäß animiert wird, wenn du ihre Größe während der Animation änderst.Verse# Calculate the multiplicative scale for the keyframe to scale to. ScaleMultiplicative:vector3 = VectorOnes + ((Scale - CreativeProp.GetTransform().Scale) / CreativeProp.GetTransform().Scale)Jede Animation benötigt ein Keyframe-Array für die Ausführung. In dieser Funktion verwendest du nur einen einzelnen Keyframe und führst einen Cast auf ein Array durch. Da dieses Array nur über einen einzelnen Keyframe verfügen wird, vollführt dein Prop eine Bewegung für die glatte Animation zu einer neuen Position. Und da du
MoveToEase()in einer Schleife aufrufen wirst, kann das Prop weiterhin animiert werden, ohne dass mehrere Animationen nacheinander festgelegt werden müssen.Definiere ein neues Array von
keyframe_deltamit der BezeichnungKeyframes. Setze dieses Array gleich einem neuen Array und erstelle in diesem Array ein neueskeyfram_delta.Verse# Build the keyframe array from a single keyframe_delta of the given values. Keyframes:[]keyframe_delta = array: keyframe_delta:Initialisiere in der
keyframe_delta-Definition jeden Wert, der für die Erstellung deines Keyframe benötigt wird. SetzeDeltaLocationauf die Differenz zwischen der neuenPositionund der Verschiebung des Kreativmodus-Prop. SetzeDeltaRotationaufRotationundDeltaScaleaufScaleMultiplicative, das du zuvor berechnet hast. SetzeTimeauf dieDurationund rufe die richtige festzulegendeInterpolationab, indem duGetCubicBezierForEaseType()aufrufst.Verse# Build the keyframe array from a single keyframe_delta of the given values. Keyframes:[]keyframe_delta = array: keyframe_delta: DeltaLocation := Position - CreativeProp.GetTransform().Translation, DeltaRotation := Rotation, DeltaScale := ScaleMultiplicative, Time := Duration, Interpolation := GetCubicBezierForEaseType(EaseType)Nachdem du dein
Keyframes-Array erstellt hast, lege es mitSetAnimation()als Animation des Animationcontrollers fest und übergib denAnimationMode. Gibt die Animation mitPlay()wieder und nutze dannAwait()fürMovementCompletedEvent. Deine vollständige ErweiterungsmethodeMoveToEase()sollte wie folgt aussehen:Verse# Animate a creative_prop by constructing an animation from a single keyframe, and then playing that animation on the prop. # This method takes a Position, Rotation, and Scale for the prop to end at, the duration of the animation, # the type of easing to apply to the movement, and the animation mode of the animation. (CreativeProp:creative_prop).MoveToEase<public>(Position:vector3, Rotation:rotation, Scale:vector3, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void= # Get the animation controller for the CreativeProp to move. if (AnimController := CreativeProp.GetAnimationController[]): # Calculate the multiplicative scale for the keyframe to scale to. ScaleMultiplicative:vector3 = VectorOnes + ((Scale - CreativeProp.GetTransform().Scale) / CreativeProp.GetTransform().Scale)
Überladen von Funktionen
Die von dir geschriebene Funktion MoveToEase() ist zwar praktisch, es kann aber kompliziert sein, bei jedem Aufruf eine derart große Anzahl Variablen an die Funktion zu übergeben. Es gibt Situationen, in denen du nur einen Teil der Transformation des Prop ändern möchtest, wie die Verschiebung oder Drehung. In diesem Fall wäre es hilfreicher, eine einfacherer Funktion zu haben.
Um das zu beheben, kannst du das Überladen der Funktion nutzen. Durch das Überladen der Funktion MoveToEase() kannst du mehrere Methoden mit dem gleichen Namen festlegen, um verschiedene Eingaben zu verarbeiten. Folge den folgenden Schritten, um deine überladenen Funktionen einzurichten.
Überlade in deiner Datei
movement_behaviorsdie FunktionMoveToEase(), indem du eine weitere Erweiterungsmethode mit dem gleichen Namen aber anderen Eingaben erstellst. DieseMoveToEase()aktualisiert nur die Verschiebung eines Prop, belässt aber die Drehung und Skalierung. Das bedeutet, dass du nur die ArgumentePosition,Duration,EaseTypeundAnimationModebenötigst.Verse# An overload of MoveToEase() that changes the position of the prop while keeping the rotation and scale the same. (CreativeProp:creative_prop).MoveToEase<public>(Position:vector3, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void=Rufe in deiner neuen
MoveToEase()die ursprüngliche FunktionMoveToEase()auf und übergib ihr alle Eingaben sowieIdentityRotation()undVectorOnesalsScale.IdentityRotation()gibt eine Drehung mit0für jeden Wert zurück, also(0,0,0). Hier benötigst duIdentityRotation(), weil du keine Drehung zu deiner Animation hinzufügen möchtest. Deine überladene FunktionMoveToEase()sollte wie folgt aussehen:Verse# An overload of MoveToEase() that changes the position of the prop while keeping the rotation and scale the same. (CreativeProp:creative_prop).MoveToEase<public>(Position:vector3, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void= CreativeProp.MoveToEase(Position, IdentityRotation(), VectorOnes, Duration, EaseType, AnimationMode)Wiederhole diesen Vorgang, um eine weitere überladene Methode zu erstellen, die nur die Drehung ändert und Verschiebung und Skalierung beibehält. Diese neue überladene Methode sollte wie folgt aussehen:
Verse# An overload of MoveToEase() that changes the rotation of the prop while keeping the position and scale the same. (CreativeProp:creative_prop).MoveToEase<public>(Rotation:rotation, Duration:float, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void= CreativeProp.MoveToEase(CreativeProp.GetTransform().Translation, Rotation, VectorOnes, Duration, EaseType, AnimationMode)Wiederhole diesen Vorgang erneut, um eine Methode zu erstellen, die nur die Skalierung ändert und Verschiebung und Drehung beibehält. Da
translationundscaleaber beidevector3sind, hätte die daraus resultierende Funktion die gleiche Signatur wie die Überladung, die du für die Verschiebung erstellt hast. Dies würde zu einem Fehler führen. Du kannst das lösen, indem du die Funktionsparameter neu anordnest. Tausche die Position vonDurationundScale, um eine überladene Funktion zu erhalten. Die überladene Methode sollte wie folgt aussehen:Verse# An overload of MoveToEase() that changes the position and scale of the prop while keeping the rotation the same. (CreativeProp:creative_prop).MoveToEase<public>(Duration:float, Scale:vector3, EaseType:move_to_ease_type, AnimationMode:animation_mode)<suspends>:void= CreativeProp.MoveToEase(CreativeProp.GetTransform().Translation, IdentityRotation(), Scale, Duration, EaseType, AnimationMode)Es ist hilfreich, über eine Version von
MoveToEase()zu verfügen, die mehrere Keyframes verarbeiten kann. Dazu kannst du deine Keyframes im Vorfeld einrichten und sie alle anMoveToEase()übergeben. Auf diese Art muss die Funktion die Animation nur auf dem Kreativmodus-Prop festlegen und wiedergeben. Füge eine neue Überladung vonMoveToEase()hinzu, die ein Keyframes-Array und den Animationsknoten als Eingabe übernimmt.Verse# An overload of MoveToEase() that takes a pre-built array of keyframes and plays an animation. (CreativeProp:creative_prop).MoveToEase<public>(Keyframes:[]keyframe_delta, AnimationMode:animation_mode)<suspends>:void= if (AnimController := CreativeProp.GetAnimationController[]): AnimController.SetAnimation(Keyframes, ?Mode:=AnimationMode) AnimController.Play() AnimController.MovementCompleteEvent.Await()Speichere deinen Code und kompiliere ihn.
Da du deine Methoden nun eingerichtet hast, können wir loslegen. Im nächsten Abschnitt wirst du Props verschieben, um sich bewegende Plattformen zu erstellen.
Vollständiger Code
Dies ist der vollständige Code, der in diesem Teil erstellt wurde:
movement_behaviors.verse
# This file stores functions common to animating creative props using keyframes.
# It also defines the move_to_ease_type enum to help in building animations.
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Characters}
using { /Fortnite.com/Devices/CreativeAnimation }
# Represents the different movement easing types.
move_to_ease_type<public> := enum {Linear, Ease, EaseIn, EaseOut, EaseInOut}