Esistono diversi modi per muovere gli oggetti scenografici in UEFN. Puoi utilizzare funzioni come TeleportTo[] o MoveTo() per modificare direttamente una trasformazione; in alternativa puoi utilizzare un altro dispositivo, ad esempio un traslatore oggetti, per spostare un oggetto scenografico su un percorso preimpostato. Tuttavia, esiste un'altra opzione utile sotto forma di animazioni.
Ogni oggetto Creativa dispone di un play_animation_controller che puoi utilizzare per riprodurre le relative animazioni. Le animazioni offrono un paio di vantaggi rispetto al movimento della trasformazione dell'oggetto scenografico. Le animazioni hanno di solito un movimento più fluido rispetto allo spostamento di oggetti con MoveTo() o TeleportTo(), perché evitano la latenza di rete dovuta alla necessità di chiamare queste funzioni a ogni tick di gioco. Le animazioni offrono anche collisioni più coerenti con i giocatori o altri oggetti, oltre a un maggior livello di controllo su dove e come si muove un oggetto rispetto all'utilizzo di un dispositivo Traslatore oggetti. Puoi riprodurre le animazioni in loop o mandarle avanti e indietro con la modalità ping-pong.
Le animazioni ti permettono anche di scegliere un tipo di interpolazione. Il tipo di interpolazione determina il tipo di attenuazione, o curva di animazione, che l'animazione segue. Ad esempio, il tipo di interpolazione lineare riproduce l'animazione a una velocità costante, mentre il tipo ease-in inizia lentamente per poi accelerare verso la fine. Scegliendo il tipo giusto di interpolazione per la tua animazione, puoi specificare in diversi punti se l'oggetto scenografico deve rallentare, accelerare o muoversi linearmente.
Passando da un'animazione all'altra per gli ostacoli, puoi creare una serie di sfide diverse per i giocatori utilizzando gli stessi oggetti scenografici. In questa sezione imparerai a utilizzare questo potente strumento per creare le tue animazioni e far muovere i tuoi oggetti scenografici!
Configurazione dei controlli di animazione
Segui i passaggi seguenti per impostare i controlli dell'animazione dei tuoi oggetti scenografici:
Utilizzando Verse Explorer, crea un nuovo file Verse denominato
movement_behaviors. Qui verranno memorizzate le funzioni di utilità necessarie per animare gli oggetti scenografici.Aggiungi le istruzioni
using { /Fortnite.com/Devices },using { /Fortnite.com/Devices/CreativeAnimation }eusing { /UnrealEngine.com/Temporary/SpatialMath }all'inizio del file per importare questi moduli. Ti serviranno per animare il tuo oggetto scenografico.In
movement_behaviors, crea un nuovoenumdenominatomove_to_ease_type. I valori di questo enum corrispondono ai diversi tipi di attenuazione dell'animazione. Puoi visualizzare ciascuno di questi tipi di alleggerimento nel moduloInterpolationTypes.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}Aggiungi
vector3come nuovo alias tipo denominatoVectorOnesche crea unvector3in cuiX,YeZsono tutti impostati su1.0. Utilizzerai questo vettore in seguito per semplificare alcuni calcoli. Definendo il relativo alias tipo non dovrai scriverevector3{X:=1.0, Y:=1.0, Z:=1.0}per più volte.Verse# Initializes a vector3 with all values set to 1.0. VectorOnes<public>:vector3 = vector3{X:=1.0, Y:=1.0, Z:=1.0}Aggiungi un nuovo Metodo
GetCubicBezierForEaseType()che prende unmove_to_ease_typee restituiscecubic_bezier_parameters.Verse# Return the cubic_bezier_parameters based on the given move_to_ease_type. GetCubicBezierForEaseType(EaseType:move_to_ease_type):cubic_bezier_parameters=Il bezier cubico è composto da quattro numeri che definiscono il tipo di funzione di attenuazione utilizzata dall'animazione. Ad esempio, i parametri di una curva ease-in fanno sì che l'animazione rallenti all'inizio e acceleri successivamente. I parametri di una curva lineare fanno sì che l'animazione venga riprodotta a velocità costante. Puoi definire questi valori in autonomia per creare le tue curve di animazione personalizzate, tuttavia in questo esempio non è necessario, poiché utilizzerai quelli definiti nel modulo
InterpolationTypes.In
GetCubicBezierForEaseType(), in un'espressionecase(), recuperacubic_bezier_parametersdal moduloInterpolationTypesin base amove_to_ease_type. Ad esempio,EaseOutdeve restituireInterpolationTypes.EaseOut,Lineardeve restituireInterpolationTypes.Lineare così via. La funzioneGetCubicBezierForEaseType()completa deve essere simile a: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.EaseInOutNella classe
movable_prop, aggiungi un nuovomove_to_ease_typemodificabile denominatoMoveEaseType. Questo è il tipo di attenuazione che l'oggetto scenografico applicherà alla propria animazione.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
Costruzione di un'animazione con keyframe
Per compilare le animazioni nel codice, utilizzerai i keyframe. Le animazioni sono costituite da uno o più keyframe e ciascuno di essi specifica i valori di un oggetto in determinati punti dell'animazione. Costruendo un'animazione tramite keyframe, puoi specificare più punti in cui il tuo oggetto scenografico deve muoversi, ruotare o addirittura ridimensionarsi.
I keyframe presentano cinque valori. I valori DeltaLocation, DeltaRotation e DeltaScale specificano le variazioni di ogni valore che l'oggetto scenografico esegue dall'inizio alla fine del keyframe. Esistono anche Time, ovvero il tempo in secondi che impiega l'animazione, e Interpolation, che corrisponde alla modalità di interpolazione per il keyframe. Un esempio di keyframe potrebbe essere il seguente:
# 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`
Segui questa procedura per creare un'animazione utilizzando i keyframe:
Aggiungi un nuovo metodo di estensione
creative_propchiamatoMoveToEase()al tuo filemovement_behaviors. Questa funzione accetta la posizione, la rotazione e la scala in base a cui deve muoversi l'oggetto scenografico, la durata dell'animazione, il tipo di attenuazione del movimento e la modalità di animazione.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=In
MoveToEase(), determina il controller dell'animazione dell'oggetto Creativa utilizzandoGetAnimationController[]. Il controller dell'animazione ti permette di riprodurre le animazioni sull'oggetto scenografico, esponendo inoltre un evento che dovrai aspettare in seguito.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[]):Calcola la variazione di scala dell'oggetto scenografico, chiamata
ScaleMultiplicative. Il valoreScaleè un po' più complesso da elaborare in questa situazione specifica. Dato che la scala è moltiplicativa, la scala della trasformazione finale deve corrispondere alla quantità di cui la trasformazione originale deve scalare, piuttosto che quella verso cui deve scalare. Ad esempio, se la scala della trasformazione originale è1.2e si desidera scalare a1.5, in realtà è necessario ridimensionare di1.25poiché1.2 * 1.25 = 1.5. Il valore finale èVectorOnespiù la differenza tra la nuova scala e la scala precedente, divisa per la scala precedente. Questo valore ti serve per assicurarti che la tua animazione continui ad animarsi correttamente se ne modifichi le dimensioni durante l'animazione.Verse# Calculate the multiplicative scale for the keyframe to scale to. ScaleMultiplicative:vector3 = VectorOnes + ((Scale - CreativeProp.GetTransform().Scale) / CreativeProp.GetTransform().Scale)Ogni animazione richiede un array di keyframe per essere eseguita. In questa funzione, utilizzerai solo un singolo keyframe e lo trasformerai in un array. Poiché questo array avrà solo un singolo keyframe, il tuo oggetto scenografico eseguirà un unico movimento per animarsi in modo fluido in una nuova posizione. E poiché chiamerai
MoveToEase()all'interno di un loop, l'oggetto scenografico può continuare ad animarsi senza dover specificare più animazioni di fila.Definisci un nuovo array di
keyframe_deltadenominatoKeyframes. Imposta questo array come nuovo array e al suo interno crea un nuovokeyfram_delta.Verse# Build the keyframe array from a single keyframe_delta of the given values. Keyframes:[]keyframe_delta = array: keyframe_delta:All'interno della definizione
keyframe_delta, inizializza ogni valore necessario per costruire il tuo keyframe. ImpostaDeltaLocationsulla differenza tra la nuovaPositione la traslazione dell'oggetto Creativa. ImpostaDeltaRotationsuRotationeDeltaScalesuScaleMultiplicativecalcolato in precedenza. ImpostaTimesuDuratione determina la giustaInterpolationda configurare chiamandoGetCubicBezierForEaseType().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)Una volta creato l'array
Keyframes, impostalo come animazione del controller dell'animazione utilizzandoSetAnimation(), mediante il passaggio diAnimationMode. Riproduci l'animazione utilizzandoPlay(), quindiAwait()MovementCompletedEvent. Il tuo metodo di estensioneMoveToEase()completo deve essere simile al seguente: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)
Sovraccarico delle funzioni
Sebbene la funzione MoveToEase() che hai scritto sia utile, può essere complicato passare un numero così elevato di variabili alla funzione ogni volta che desideri chiamarla. Potrebbero verificarsi delle situazioni in cui vuoi cambiare solo una parte della trasformazione dell'oggetto scenografico, come ad esempio la traslazione o la rotazione, e sarebbe utile disporre di una funzione più semplice da chiamare in questo caso.
Per risolvere questo problema, puoi sfruttare l'overloading della funzione. Sovraccaricando la funzione MoveToEase(), puoi impostare più metodi con lo stesso nome per gestire vari tipi di input. Segui i passaggi seguenti per impostare le tue funzioni sovraccaricate.
Nel file
movement_behaviors, sovraccarica la funzioneMoveToEase()creando un altro metodo di estensione con lo stesso nome, ma con input diversi. La funzioneMoveToEase()aggiornerà solo la traslazione di un oggetto scenografico, lasciando invariate la rotazione e la scala. Ciò significa che sono necessari solo gli argomentiPosition,Duration,EaseTypeeAnimationMode.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=Nella nuova funzione
MoveToEase(), richiama la funzione originaleMoveToEase(), passando tutti gli input piùIdentityRotation()eVectorOnescomeScale. La funzioneIdentityRotation()restituisce una rotazione con ogni valore a0, quindi(0,0,0). In questo caso, ti serveIdentityRotation()perché non desideri aggiungere una rotazione alla tua animazione. La funzione sovraccaricataMoveToEase()deve essere simile alla seguente: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)Ripeti questo processo per creare un altro metodo sovraccaricato che modifichi solo la rotazione, mantenendo invariate la traslazione e la scala. Questo nuovo metodo sovraccaricato deve essere simile a:
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)Ripeti di nuovo per creare un metodo che modifichi solo la scala, mantenendo invariate la traslazione e la rotazione. Tuttavia, poiché
translationescalesono entrambevector3, la funzione risultante avrebbe la stessa firma del sovraccarico che hai eseguito per la traslazione, generando un errore. Puoi risolvere questo problema riordinando i parametri della funzione. Scambia la posizione diDurationeScaleper avere la funzione sovraccaricata. Il metodo sovraccaricato deve essere simile a: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)È utile disporre di una versione di
MoveToEase()che possa gestire più keyframe. Puoi gestire questo problema impostando in anticipo i tuoi keyframe e passandoli tutti aMoveToEase(). In questo modo, la funzione deve solo impostare e riprodurre l'animazione sull'oggetto scenografico Creativo. Aggiungi un nuovo sovraccarico diMoveToEase()che considera come input un array di keyframe e la modalità di animazione.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()Salva il codice e compilalo.
Una volta impostati i tuoi metodi, è giunto il momento di mettersi all'opera! Nella prossima sezione, traslerai gli oggetti scenografici per creare piattaforme mobili!
Codice completo
Ecco il codice completo compilato in questa sezione:
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}