Il passo successivo agli oggetti che si muovono, ruotano o scalano è quello di eseguire tutte e tre le operazioni contemporaneamente. Tuttavia, vi sono alcune sfide importanti da considerare quando si costruiscono animazioni per oggetti scenografici che si muovono in più modi contemporaneamente.
Poiché il controller dell'animazione può riprodurre solo un'animazione alla volta, non è possibile eseguire il movimento, la rotazione e il ridimensionamento in animazioni separate. Queste animazioni richiedono anche più keyframe, perché potresti ruotare un oggetto scenografico più volte per ogni animazione. Poiché devi costruire tutti i keyframe in anticipo, devi anche calcolare la posizione, la rotazione e la scala in ogni punto del percorso dell'oggetto scenografico. Cosa succede se il tuo oggetto scenografico non compie un numero uniforme di rotazioni? Come gestisci una mezza rotazione?
In questa sezione è coinvolta molta matematica, ma quando la terminerai sarai in grado di muovere, ruotare e scalare gli oggetti scenografici in più punti e di creare oggetti complessi, dinamici e (cosa più importante!) sfide della piattaforma divertenti per costruire il percorso Fall Guys dei tuoi sogni.
Costruzione di animazioni che si muovono, ruotano e scalano
Segui questa procedura per iniziare a organizzare il tutto:
Crea una nuova classe Verse denominata
animating_propche eredita damovable_proputilizzando Verse Explorer. Aggiungi lo specificatore<concrete>a questa classe per esporre le proprietà a UEFN.Verse# A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):Aggiungi le istruzioni
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. I tooltip utilizzati in questa sezione sono inclusi anche qui.Verseusing { /Fortnite.com/Devices } using { /Fortnite.com/Devices/CreativeAnimation } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/SpatialMath } RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds." UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame." # A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):All'inizio della definizione della classe
animating_prop, aggiungi i seguenti campi:Una
rotationmodificabile denominataAdditionalRotation. Questa è la rotazione da applicare aRootPropper keyframe.Verse# The additional rotation to apply to the RootProp per keyframe. @editable {ToolTip := AdditionalRotationTip} AdditionalRotation:rotation = rotation{}Floatmodificabile denominatoRotationRate. È il tempo necessario per eseguireAdditionalRotationin secondi.Verse# The time it takes to make one AdditionalRotation in seconds. @editable {ToolTip := RotationRateTip} var RotationRate:float = 1.0Logicmodificabile denominataUseEasePerKeyFrame. Ciò determina se ogni keyframe utilizzaMoveEaseTypeper l'interpolazione. In questo esempio, impostando questo valore sufalsosi utilizzerà per impostazione predefinita il tipo di interpolazione lineare per ogni frame.Verse# Whether this prop should use the MoveEaseType per each frame of animation. # Setting this to false will use the linear MoveEaseType on each frame. @editable UseEasePerKeyframe:logic = trueArray modificabile di
creative_propdenominatoMoveTargets. Questi sono i diversi oggetti scenografici Creativo verso cui si dirigerà il tuo oggetto scenografico principale.Verse# The Creative prop target for the RootProp to move toward. @editable {ToolTip := MoveTargetsTip} var MoveTargets:[]creative_prop = array{}Variabile
transformdenominataTargetTransform. Questa è la trasformazione verso la quale si sta dirigendo il tuo oggetto scenografico principale.Verse# The transform the prop is currently targeting. var TargetTransform:transform = transform{}
La tua definizione della classe deve essere simile a:
Verseusing { /Fortnite.com/Devices } using { /Fortnite.com/Devices/CreativeAnimation } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/SpatialMath } RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds." UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame." # A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):Esegui l'override della funzione
Move()nella classeanimating_prop. Quindi, in un'espressionefor, itera ogniMoveTargetnell'arrayMoveTargets. Controlla se ogniMoveTargetè valido e, in caso affermativo, impostaTargetTransformsulla trasformazione diMoveTarget.Verse# Move and rotate the RootProp toward the MoveTarget, or MoveTransform if one is set. Move<override>()<suspends>:void= # Move to each target in the MoveTargets array. for: MoveTarget:MoveTargets do: # Set the TargetTransformto the MoveTarget if the # MoveTarget is set. Otherwise set it to the MoveTransform.Nel file
movement_behaviors, aggiungi un nuovo metodo denominatoBuildMovingAnimationKeyframes(). Questa funzione costruisce e restituisce un array di keyframe che animano un oggetto scenografico che si muove e ruota in base a una trasformazione bersaglio. Questa funzione prende diversi parametri daanimating_prop:MoveDuration,RotationRate,AdditionalRotation,OriginalTransform(trasformazione iniziale dell'oggetto scenografico),TargetTransform,MoveEaseTypee un nuovo valorelogicdenominatoUseEasePerKeyframe. Determina se utilizzareMoveEaseTypeper ogni keyframe. La firma della tua funzione deve essere simile a:Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta=In
BuildMovingAnimationKeyframes(), inizializza le variabili seguenti:Array variabile di
keyframe_deltadenominatoKeyframes. Questo è l'array che restituirai alla fine.Verse# The array of keyframes to return. var KeyFrames:[]keyframe_delta = array{}Variabile
floatdenominataTotalTime. Questo è il tempo totale trascorso per l'animazione fino a ora.Verse# The total amount of time spent animating. var TotalTime:float = 0.0Due variabili
transformdenominateStartTransformeEndTransform. Queste sono le trasformazioni iniziali e finali dell'oggetto scenografico all'inizio e al termine di ogni keyframe. Inizializza entrambe conOriginalTransform.Verse# The starting transform for building keyframes. This is the # transform of the RootProp at the start of each keyframe. var StartTransform:transform = OriginalTransform # The ending transform for building keyframes. This is the # transform of the RootProp at the end of each keyframe. var EndTransform:transform = OriginalTransformVariabile
rotationdenominataRotationToApply, inizializzata conAdditionalRotation. Questa è la rotazione effettiva che applicherai all'oggetto scenografico per ogni keyframe. Di solito, questo valore èAdditionalRotation, ma se devi eseguire una rotazione frazionaria dovrai modificare tale valore.Verse# The actual rotation to apply to the RootProp. Usually this is the # AdditionalRotation, but will change in cases with fractional rotations. var RotationToApply:rotation = AdditionalRotationVariabile
FloatdenominataAnimationTime. Corrisponde al tempo in secondi che impiega ogni keyframe. Inizializza questo valore con1.0/RotationRate, perché RootProp deve eseguire un numero di rotazioni al secondo pari aRotationRate.Verse# The time it takes for each keyframe of animation to complete. # This is initialized to 1.0/Rotation rate since the RootProp needs to make a # RotationRate number of rotations per second. var AnimationTime:float = 1.0 / RotationRateValore
floatdenominatoTotalRotations. Questo è il numero totale di rotazioni da eseguire nell'intera animazione ed è inizializzato conMoveDuration * RotationRate. Il motivo per cui questo è unfloate non unintdipende dal fatto che deve gestire le situazioni in cui non è necessario eseguire una rotazione completa, come al termine di un'animazione.Verse# The total number of rotations to make. TotalRotations:float = MoveDuration * RotationRateValore
floatdenominatoTimePerRotation. Corrisponde al tempo in secondi necessario per completare una rotazione. Ora la tua funzione deve avere un aspetto simile.Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta= # The array of keyframes to return. var KeyFrames:[]keyframe_delta = array{} # The total amount of time spent animating. var TotalTime:float = 0.0 # The starting transform for building keyframes. This is the
Sono numerosi i valori di cui tenere traccia, quindi facciamo un esempio di calcolo, utilizzando 2.5 come RotationRate e 5.0 come MoveDuration.
Rotation Rate = 2.5 rotations/second
Move Duration = 5.0 seconds
Animation Time =
1.0 seconds/Rotation Rate =
1.0/2.5 = 0.4 seconds
Total Rotations =
Move Duration /Rotation Rate =
Con un RotationRate di 2.5 e un MoveDuration di 5.0, eseguirai un totale di 12.5 rotazioni, ognuna delle quali richiede 0.4 secondi. Ciò significa che dovrai eseguire una mezza rotazione in più al termine dell'animazione. Potresti anche notare che il tempo di animazione e il tempo per rotazione sono gli stessi. Ciò accade quasi sempre, tranne quando devi eseguire meno di una rotazione completa. Anche se inizialmente presentano lo stesso valore, dovrai tenere traccia di entrambe le variabili per gestire alcuni calcoli successivi.
Creazione di keyframe in loop
È ora di iniziare a costruire. Segui i passaggi seguenti per impostare il loop che costruisce i keyframe.
Aggiungi un'espressione
loopaBuildMovingAnimationKeyframes(). A ogni iterazione del loop, creerai un nuovo keyframe e lo aggiungerai all'array dei keyframe. All'inizio del loop, aggiornaTotalTimeconTimePerRotation.Verse# Build each keyframe of animation and add it to the Keyframes array. # The loop breaks when the TotalTime goes past the MoveDuration. loop: # Add the TimePerRotation to the TotalTime. set TotalTime += TimePerRotationCompila
EndTransformche è il punto in cui l'oggetto scenografico deve trovarsi alla fine di questo keyframe. ImpostaEndTransformsu una nuova trasformazione con i parametri seguenti:Imposta
Translationsul risultato della chiamata diLerp()traOriginalTransformeTargetTransform. La funzioneLerp()accetta due valori e un rapporto Lerp compreso tra0.0e1.0. Quindi genera un nuovo valore che si trova a metà tra i due in base al rapporto Lerp. Più il rapporto Lerp è vicino a 1.0, più la trasformazione sarà vicina aTargetTransforme viceversa.Verse# Build the ending transform for the RootProp to move to. set EndTransform = transform: # Use Lerp() to find how far between the StartingTransform and the TargetTransform the RootProp should translate. # Do the same for scale, and rotate the starting transform by the RotationToApply. # The Lerp Parameter is based on the total number of rotations since the RootProp should guarantee that it makes # at least that many rotations over the whole animation. Translation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, (TotalTime * RotationRate) / (TotalRotations))Imposta
Rotationsul risultato diMakeShortestRotationBetween(), passando la rotazione della trasformazione originale e quest'ultima ruotata daRotationToApply.VerseTranslation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, (TotalTime * RotationRate) / (TotalRotations)) Rotation := MakeShortestRotationBetween(OriginalTransform.Rotation, OriginalTransform.Rotation.RotateBy(RotationToApply))~~~Imposta
Scalesul risultato della chiamata aLerp()traOriginalTransform.ScaleeTargetTransform.Scale. Tieni presente che questa è la scala in base a cui l'oggetto scenografico deve ridimensionarsi, non la quantità di cui deve scalare. Il tuoEndTransformcompleto deve essere simile al seguente:Verse# Build the ending transform for the RootProp to move to. set EndTransform = transform: # Use Lerp() to find how far between the StartingTransform and the TargetTransform the RootProp should translate. # Do the same for scale, and find the shortest rotation between the original transform and a rotation to apply to it. Translation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, LerpParameter) Rotation := MakeShortestRotationBetween(OriginalTransform.Rotation, OriginalTransform.Rotation.RotateBy(RotationToApply)) Scale := Lerp(OriginalTransform.Scale, TargetTransform.Scale, LerpParameter)
Una volta impostata la trasformazione finale, è il momento di costruire un keyframe. Questo è in gran parte lo stesso processo che hai eseguito per la tua funzione
MoveToEase(). Crea una nuova variabilekeyframe_deltadenominataKeyFrame. ImpostaDeltaLocationsulla differenza tra le traslazioni della trasformazione finale e iniziale. ImpostaDeltaRotationsulla rotazione della trasformazione finale. Poiché è necessario calcolare la variazione di scala, impostaDeltaScalesul risultato della divisione della scala della trasformazione finale per la scala della trasformazione iniziale.Timedeve essereAnimationTimeeInterpolationTypedeve essere il risultato di un'espressioneif. SeUseEasePerKeyframeè vero, utilizzaMoveEaseType. In caso contrario, utilizza il tipo lineare. La tua espressione del keyframe deve essere simile a ciò:Verse# Build the animation keyframe to animate the RootProp. Keyframe := keyframe_delta: DeltaLocation := EndTransform.Translation - StartTransform.Translation, DeltaRotation := EndTransform.Rotation, DeltaScale := EndTransform.Scale/StartTransform.Scale, Time := AnimationTime, # Use the MoveEaseType for interpolation if UseEasePerKeyframe is true, # otherwise use the Linear movement type. Interpolation := if:Una volta creato il tuo keyframe, ora puoi aggiungerlo all'array
Keyframes. Quindi impostaStartTransformsuEndTransformper aggiornarla per il keyframe successivo. Infine, seTotalTimeè ora maggiore diMoveDuration, interrompi il loop.Verse# Add the new keyframe to the KeyFrames array, and set the # StartTransform to the EndTransform. set Keyframes += array{Keyframe} set StartTransform = EndTransform # Break out of the loop if the TotalTime passes the MoveDuration. if: TotalTime >= MoveDuration then: breakEsiste un caso limite importante da considerare: che cosa accade quando devi eseguire meno di una rotazione completa? Dato che stai aggiungendo
TimePerRotationaTotalTime, ciò significa cheTotalTimepotrebbe essere superiore aMoveDurationall'inizio del loop. In questa situazione, devi gestire il tempo residuo ed eseguire una rotazione inferiore a quella completa, con un tempo di animazione più breve per tenere conto della differenza. Segui questa procedura per tenere conto di questa situazione:All'inizio del loop, dopo aver aggiornato
TotalTime, inizia un'espressioneif. All'interno, inizializza una variabileLeftoverTimee impostala uguale al risultato della sottrazione diTotalTimeeMoveDuration, verificando che sia maggiore di0.0. Questa espressione assegneràLeftoverTimesolo se il confronto è vero.Verseloop: # Add the TimePerRotation to the TotalTime. set TotalTime += TimePerRotation if: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0Per sapere quale frazione di rotazione devi eseguire, inizializza una nuova variabile
`Roation Fraction`,e impostala uguale alla differenza tra`TimePerRotation`e`LeftoverTime`,tutti divisi per`TimePerRotation`.Verseif: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0 # The fraction of a rotation to make. RotationFraction := (TimePerRotation - LeftoverTime)/TimePerRotationPer costruire una rotazione modificata a partire da
RotationFraction, utilizzeraiSlerp[]. Questa è la versione diLerp()che gestisce l'interpolazione sferica e offre parametri simili. Trova la rotazione più breve tra due rotazioni diverse e restituisce una rotazione basata sul parametro lerp. ChiamaSlerp[], interpolando traIdentityRotation()eIdentityRotation()ruotata daRotationToApply, utilizzandoRotationFractioncome parametro lerp. Stai utilizzandoIdentityRotation()in questo caso perché ti interessa solo trovare la rotazione frazionaria da applicare, non la rotazione finale a cui deve trovarsiEndTransform.Verseset TotalTime += TimePerRotation if: # If the TotalTime is greater than the MoveDuration, the final keyframe needs # to be shortened. This means making a fraction of a rotation. LeftoverTime := TotalTime - MoveDuration > 0.0 # The fraction of a rotation to make. RotationFraction := (TimePerRotation - LeftoverTime)/TimePerRotation # Make a modified fractional rotation by using Slerp(). The Slerp() function does spherical interpolationUna volta impostati questi valori, imposta
RotationToApplysuModifiedRotation, moltiplicaAnimationTimeperRotationFractionper sapere di quanto abbreviare l'animazione e infine impostaTotalTimesuMoveDurationpoiché non vuoi che sia maggiore di questo valore quando calcoliEndTransform.VerseModifiedRotation := Slerp[IdentityRotation(), IdentityRotation().RotateBy(RotationToApply), RotationFraction] then: # Set the RotationToApply to the modified rotation, and multiply the animation time by # the RotationFraction to get the modified animation time. set RotationToApply = ModifiedRotation set AnimationTime = AnimationTime * RotationFraction # Since the TotalTime should not go past the MoveDuration, # set TotalTime to MoveDuration. set TotalTime = MoveDuration
Al termine della funzione, dopo il loop, restituisci l'array
Keyframes. La funzioneBuildMovingAnimationKeyframes()completa deve essere simile alla seguente:Verse# Builds an array of keyframes that animate movement and rotation from the OriginalTransform to the TargetTransform. BuildMovingAnimationKeyframes(MoveDuration:float, RotationRate:float, AdditionalRotation:rotation, OriginalTransform:transform, TargetTransform:transform,MoveEaseType:move_to_ease_type, UseEasePerKeyframe:logic):[]keyframe_delta= # The array of keyframes to return. var Keyframes:[]keyframe_delta = array{} # The total amount of time spent animating. var TotalTime:float = 0.0 # The starting transform for building keyframes. This is theOra che hai definito la logica per costruire i tuoi keyframe, è il momento di animarli. Utilizzerai una funzione separata per costruire e chiamare la tua animazione. Aggiungi una nuova funzione
BuildAndPlayAnimation()alla tua classeanimating_prop. Aggiungi il modificatore<suspends>a questa funzione per permettere di chiamare altre funzioni asincrone.Verse# Builds an animation from an array of keyframes, then calls MoveToEase() # to animate the prop. BuildAndPlayAnimation()<suspends>:void=In
BuildAndPlayAnimation(), inizializza un nuovo arraykeyframe_deltadenominatoKeyframes. Quindi impostaKeyframessul risultato della chiamata aBuildMovingAnimationKeyframes(). UtilizzaRootProp.GetTransform()come trasformazione iniziale poiché la posizione dell'oggetto scenografico cambierà tra le chiamateMove(). Inizializza una variabileanimation_modeconanimation_mode.OneShote chiamaMoveToEase(), passando l'arrayKeyframeseAnimationMode.La funzione
BuildAndPlayAnimation()completa deve essere simile alla seguente:Verse# Builds an animation from an array of keyframes, then calls MoveToEase() # to animate the prop. BuildAndPlayAnimation()<suspends>:void= var Keyframes:[]keyframe_delta = array{} # Build the animation, using the RootProp as the target transform. set Keyframes = BuildMovingAnimationKeyframes(MoveDuration, RotationRate, AdditionalRotation, RootProp.GetTransform(), TargetTransform, MoveEaseType, UseEasePerKeyframe) # Set the animation mode to OneShot. var AnimationMode:animation_mode := animation_mode.OneShotTorna in
Move(), chiamaBuildAndPlayAnimation()dopo aver impostatoTargetTransformsulla trasformazione dei bersagli di spostamento.Verse# Move to each target in the MoveTargets array. for: MoveTarget:MoveTargets do: # Set the TargetTransform to the MoveTarget if the # MoveTarget is set. Otherwise set it to the MoveTransform. if: MoveTarget.IsValid[] then: set TargetTransform = MoveTarget.GetTransform()
Occorre considerare anche un altro caso. Che cosa succede se non imposti alcun bersaglio di movimento? In questa situazione, il tuo oggetto scenografico deve continuare a ruotare in posizione, senza muoversi verso una nuova destinazione. Per gestire questo problema, aggiungi un'espressione if all'inizio della funzione Move(). Nell'espressione if, controlla se MoveTargets.Length = 0 e, in tal caso, imposta TargetTransform sulla trasformazione dell'oggetto scenografico principale. Quindi chiama BuildAndPlayAnimation(). In questo modo, l'oggetto scenografico continuerà ad animarsi anche se non hai impostato un bersaglio di movimento. L'animazione Move() completa deve essere simile a questa:
# Move and rotate the RootProp toward the MoveTarget, or MoveTransform if one is set.
Move<override>()<suspends>:void=
# If there are no targets to move to, this prop will rotate in place.
if:
MoveTargets.Length = 0
then:
set TargetTransform = RootProp.GetTransform()
# Build and play the animation.
BuildAndPlayAnimation()
Ora devi fare riferimento a animating_prop nella tua classe prop_animator. In prop_animator, aggiungi un array modificabile di animating_prop denominato MoveAndRotateProps. In OnBegin(), in un'altra espressione for, inizializza ogni oggetto scenografico in MoveAndRotateProps chiamando Setup(). La tua classe completa prop_animator deve essere simile a:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
TranslatingPropsTip<localizes>:message = "The props that translate (move) using animation."
RotatingPropsTip<localizes>:message = "The props that rotate using animation."
ScalingPropsTip<localizes>:message = "The props that scale using animation."
AnimatingPropsTip<localizes>:message = "The props that both move and rotate using animation."
# Coordinates moving props through animation by calling each movable_prop's Setup() method.
Salva il codice e compilalo.
Congratulazioni, il codice è stato completato! Ora è il momento di collegare tutti gli elementi.
La classe animating_prop che hai appena creato può muovere, ruotare e ridimensionare gli oggetti scenografici. Tuttavia, dipende ancora dalla classe moveable_prop perché deve ereditare varie funzioni come ManageMovement(). Dato che la classe animating_prop può eseguire tutti e tre i tipi di movimento, potrebbe essere utile rifattorizzare animating_prop per includere l'intera logica di moveable_prop in modo che la classe possa essere indipendente. Qui è incluso un esempio di refactoring che unisce animating_prop e moveable_prop in un unico file. Include anche la classe di dispositivi Verse prop_animator. Avrai ancora bisogno delle funzionalità di movement_behaviors per far funzionare il tuo codice, ma questa rifattorizzazione riduce il numero di file necessari da cinque a due. Questo codice è incluso anche nella Sezione codice completo.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
EasingCategory<localizes>:message := "These control the type of movement easing applied to the prop."
LogicCategory<localizes>:message := "These control different aspects of the prop's logic."
PropsCategory<localizes>:message := "These are the props that move associated with this device."
RotationCategory<localizes>:message := "These control how the prop rotates."
TimingCategory<localizes>:message := "These control the timing of parts of the prop's movmement."
Collegamento degli oggetti scenografici ai dispositivi
Nell'editor, elimina una sezione del percorso dopo la sezione degli oggetti scenografici rotanti per creare uno spazio prima dell'obiettivo finale. Aggiungi un'altra FG01 SpinningBar Double S e FG01 Piattaforma fluttuante M al tuo livello. Denominale **SpinningMovingBar** e **TranslatingPlatform**, quindi aggiungi diversi oggetti scenografici lampadina pulsante FG01 che saranno i Target verso cui si sposterà ogni oggetto scenografico. Denomina questi PlatformTarget. Posiziona le piattaforme e la barra sopra lo spazio e assicurati di collocare i target nel punto in cui vuoi che si muovano le piattaforme. In questo esempio, la barra di rotazione si muove da un lato all'altro, mentre la piattaforma si sposta avanti e indietro.
Configurazione della barra di rotazione e della piattaforma mobile. Le frecce indicano in quali direzioni si muove ogni oggetto scenografico. Sia la barra che la piattaforma si muovono avanti e indietro e la barra gira mentre si muove.
Seleziona il tuo animatore di oggetto scenografico nell'Outliner. Aggiungi un elemento dell'array a AnimatingProps per la barra rotante. Imposta ogni valore come segue:
| Opzione | Valore | Spiegazione |
|---|---|---|
Rotazione aggiuntiva | 90.0 | Questo oggetto scenografico eseguirà ogni volta una rotazione di 90 gradi. |
Velocità di rotazione | 1.5 | Questo oggetto scenografico compie una rotazione ogni |
Utilizza smussatura per keyframe | falso | Utilizzerà il tipo di attenuazione lineare su ogni keyframe per muovere e ruotare l'oggetto scenografico a una velocità costante. |
MoveTargets | 2 elementi, assegnati ai target della piattaforma. | Questi sono i target verso cui vuoi che la barra si muova. |
RootProp | SpinningMovingBar | Questo è l'oggetto scenografico che stai animando. |
Aggiungi un altro elemento dell'array a TranslatingProps per la tua piattaforma mobile. Assegna MoveTargets ai target della tua piattaforma e RootProp alla TranslatingPlatform.
Premi Avvia sessione e prova a correre nel tuo percorso a ostacoli completo!
In autonomia
E questo è tutto! Ora hai tutto ciò che ti occorre per creare il tuo percorso a ostacoli di Fall Guys con Verse!
Puoi utilizzare il codice qui per animare gli oggetto scenografico Creativo in tutte le tue esperienze, non solo nei progetti di Fall Guys!
Utilizzando quanto appreso, prova a fare quanto segue:
Crea ostacoli che ruotano in diverse direzioni o che ruotano in modo casuale attraverso i keyframe.
Crea ostacoli che si attivano solo quando un giocatore ci passa sopra o si avvicina a una certa distanza.
Scopri come creare piattaforme che scompaiono dopo una certa durata o che spostano i giocatori in posizioni pericolose, se ci rimangono sopra troppo a lungo.
Codice completo
Ecco il codice completo compilato in questa sezione, incluso un esempio di refactoring per animating_prop.
movable_prop.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MoveDurationTip<localizes>:message = "The amount of time the prop takes to move to its destination."
MoveEaseTypeTip<localizes>:message = "The animation easing applied to the movement."
MoveEndDelayTip<localizes>:message = "The delay after the movement finishes."
MoveOnceAndStopTip<localizes>:message = "Whether the RootProp should stop in place after it finishes moving."
MoveStartDelayTip<localizes>:message = "The delay before the movement starts."
MoveTargetsTip<localizes>:message = "The array of CreativeProp to move toward. These targets can be children of the RootProp."
translating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MovePositionTip<localizes>:message = "The optional position to move to World Space. Use this if you do not want to set a MoveTarget."
# A prop that moves (translates) toward either a Creative prop target
# or a position in world space.
translating_prop<public> := class<concrete>(movable_prop):
rotating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
AdditionalRotationTip<localizes>:message = "The rotation to apply to the RootProp."
ShouldRotateForeverTip<localizes>:message = "Whether the RootProp should rotate forever."
MatchRotationTargetTip<localizes>:message = "The optional prop whose rotation the RootProp should rotate to. Use this if you do not want to set an Additional Rotation."
# A prop that rotates by an additional rotation or rotates to match
scaling_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
MatchScaleTargetTip<localizes>:message = "The optional position to move to World Space. Use this if you do not want to set a MoveTarget."
# A prop that scales toward either a given scale or a Creative prop's scale.
scaling_prop<public> := class<concrete>(movable_prop):
# The array of vector3 targets for the RootProp to scale to.
animating_prop.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
RotationRateTip<localizes>:message := "The time it takes to make one AdditionalRotation in seconds."
UseEasePerKeyframeTip<localizes>:message := "Whether this prop should use the MoveEaseType for each keyframe. False will use the Linear ease type on each frame."
# A prop that translates, rotates, and scales to a destination using animation.
animating_prop<public> := class<concrete>(movable_prop):
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}
prop_animator.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
TranslatingPropsTip<localizes>:message = "The props that translate (move) using animation."
RotatingPropsTip<localizes>:message = "The props that rotate using animation."
ScalingPropsTip<localizes>:message = "The props that scale using animation."
MoveAndRotatePropsTip<localizes>:message = "The props that both move and rotate using animation."
# Coordinates moving props through animation by calling each moveable_prop's Setup() method.
animating_props.verse (esempio di refactoring di animating_prop)
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
EasingCategory<localizes>:message := "These control the type of movement easing applied to the prop."
LogicCategory<localizes>:message := "These control different aspects of the prop's logic."
PropsCategory<localizes>:message := "These are the props that move associated with this device."
RotationCategory<localizes>:message := "These control how the prop rotates."
TimingCategory<localizes>:message := "These control the timing of parts of the prop's movmement."