La etapa siguiente a los objetos que se mueven, rotan o escalan es hacer las tres cosas a la vez. No obstante, a la hora de crear animaciones para elementos que se mueven de varias maneras al mismo tiempo, hay que tener en cuenta algunos problemas importantes.
Como el controlador de animación solo puede reproducir una animación a la vez, no puedes hacer el movimiento, la rotación y la escala en animaciones separadas. Estas animaciones también necesitan múltiples fotogramas clave, ya que es posible que quieras rotar un elemento varias veces por animación. Como tienes que construir todos los fotogramas clave con antelación, también tienes que calcular la posición, la rotación y la escala en cada punto del recorrido del elemento. ¿Qué ocurre si el elemento no realiza el mismo número de rotaciones? ¿Cómo se puede gestionar media rotación?
En esta sección habrá un montón de matemáticas, pero al final serás capaz de mover, rotar y escalar elementos a múltiples puntos, y crear elementos complejos, dinámicos y (¡lo más importante!) divertidos desafíos de plataformas para hacer el recorrido de Fall Guys de tus sueños.
Cómo crear animaciones con movimiento, rotación y escala
Sigue los pasos que se indican a continuación para empezar a poner todo en orden:
Crea una nueva clase de Verse con el nombre
animating_propque herede demovable_propmediante el explorador de Verse. Añade el especificador<concrete>a esta clase para exponer sus propiedades a UEFN.Verse# A prop that translates, rotates, and scales to a destination using animation. animating_prop<public> := class<concrete>(movable_prop):Añade las declaraciones
using { /Fortnite.com/Devices/CreativeAnimation }yusing { /UnrealEngine.com/Temporary/SpatialMath }en la parte superior del archivo para importar estos módulos. Necesitarás estos módulos para animar el elemento. También se incluyen aquí los consejos utilizados en esta sección.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):En la parte superior de la definición de la clase
animating_prop, añade los siguientes campos:Una
rotationeditable con el nombreAdditionalRotation. Esta es la rotación que se aplicará alRootProppor fotograma clave.Verse# The additional rotation to apply to the RootProp per keyframe. @editable {ToolTip := AdditionalRotationTip} AdditionalRotation:rotation = rotation{}Un
floateditable con el nombreRotationRate. Esta es la cantidad de tiempo que se tarda en realizar unaAdditionalRotation, en segundos.Verse# The time it takes to make one AdditionalRotation in seconds. @editable {ToolTip := RotationRateTip} var RotationRate:float = 1.0Una
logiceditable con el nombreUseEasePerKeyFrame. Esto determina si cada fotograma clave utiliza elMoveEaseTypepara la interpolación. En este ejemplo, al establecer este valor enfalse, se utilizará de forma predeterminada el tipo de interpolación lineal para cada fotograma.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 = trueUna matriz editable de
creative_propcon el nombreMoveTargets. Estos son los diferentes elementos del modo Creativo a los que se desplazará tu elemento raíz.Verse# The Creative prop target for the RootProp to move toward. @editable {ToolTip := MoveTargetsTip} var MoveTargets:[]creative_prop = array{}Una variable
transformcon el nombreTargetTransform. Esta es la transformación a la que se desplaza actualmente tu elemento raíz.Verse# The transform the prop is currently targeting. var TargetTransform:transform = transform{}
La definición de la clase debería tener este aspecto:
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):Anula la función
Move()en tu claseanimating_prop. Después, en una expresiónfor, itera cadaMoveTargetde la matrizMoveTargets. Comprueba si cadaMoveTargetes válido y, en caso afirmativo, establece laTargetTransformen la transformación delMoveTarget.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.En el archivo
movement_behaviors, añade un nuevo método con el nombreBuildMovingAnimationKeyframes(). Esta función construirá y devolverá una matriz de fotogramas clave que animan un elemento que se mueve y rota hacia una transformación objetivo. Esta función recibe varios parámetros deanimating_prop:MoveDuration,RotationRate,AdditionalRotation,OriginalTransform(la transformación inicial del elemento),TargetTransform,MoveEaseTypey un nuevo valorlogiccon el nombreUseEasePerKeyframe. Esto determina si se utiliza elMoveEaseTypepara cada fotograma clave. La firma de la función debería tener el siguiente aspecto: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=En
BuildMovingAnimationKeyframes(), inicializa las siguientes variables:Una matriz variable de
keyframe_deltadenominadaKeyframes. Esta es la matriz que devolverás al final.Verse# The array of keyframes to return. var KeyFrames:[]keyframe_delta = array{}Una variable
floatcon el nombreTotalTime. Esta es la cantidad total de tiempo invertido en la animación hasta el momento.Verse# The total amount of time spent animating. var TotalTime:float = 0.0Dos variables
transformcon los nombresStartTransformyEndTransform. Estas son las transformaciones iniciales y finales del elemento al inicio y al final de cada fotograma clave. Inicializa las dos aOriginalTransform.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 = OriginalTransformUna variable
rotationcon el nombreRotationToApply, inicializada con el valorAdditionalRotation. Esta es la rotación actual que se aplicará al elemento para cada fotograma clave. Por lo general, será laAdditionalRotation, pero si necesitas hacer una rotación fraccional tendrás que cambiar este valor.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 = AdditionalRotationUna variable
floatcon el nombreAnimationTime. Esta es la cantidad de tiempo en segundos que tarda cada fotograma clave. Inicializa este valor a1.0 / RotationRate, ya que el RootProp necesita hacer un número de rotacionesRotationRatepor segundo.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 / RotationRateUn valor
floatcon el nombreTotalRotations. Este es el número total de rotaciones que se van a realizar a lo largo de toda la animación, y se inicializa enMoveDuration * RotationRate. El motivo por el que esto es unfloaty no unintes para lidiar con situaciones en las que no necesitas hacer una rotación completa, como al final de una animación.Verse# The total number of rotations to make. TotalRotations:float = MoveDuration * RotationRateUn valor
floatcon el nombreTimePerRotation. Esta es la cantidad de tiempo en segundos que tarda una rotación en completarse. Tu función debería tener ahora el siguiente aspecto.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
Hay muchos valores a tener en cuenta, así que vamos a hacer un cálculo de ejemplo, utilizando 2.5 como RotationRate y 5.0 como 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 una RotationRate de 2.5 y una MoveDuration de 5.0, harás 12.5 rotaciones en total, cada una de las cuales tardará 0.4 segundos. Esto quiere decir que tendrás que hacer una media rotación extra al final de la animación. Además, puedes observar que el tiempo de animación y el tiempo por rotación son los mismos. Casi siempre es así, excepto cuando se necesita hacer menos de una rotación completa. Aunque inicialmente tengan el mismo valor, necesitarás tener un registro de ambas variables para poder realizar algunas operaciones matemáticas posteriores.
Cómo crear fotogramas clave en un bucle
¡Ha llegado el momento de empezar a construir! Sigue los pasos que se indican a continuación para configurar el bucle que construye tus fotogramas clave.
Añade una expresión
loopaBuildMovingAnimationKeyframes(). En cada iteración del bucle, construirás un nuevo fotograma clave y lo añadirás a la matriz de fotogramas clave. Al inicio del bucle, actualiza elTotalTimecon elTimePerRotation.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 la
EndTransform, que es donde debería estar el elemento al final de este fotograma clave. Establece laEndTransforma una nueva transformación con los siguientes parámetros:Establece la
Translational resultado de llamar aLerp()entre laOriginalTransformy laTargetTransform. La funciónLerp()recibe dos valores y una relación de interpolación lineal entre0.0y1.0. Posteriormente, genera un nuevo valor intermedio basado en la relación de interpolación lineal. Cuanto más se acerque la relación de interpolación lineal a 1.0, más se acercará la transformación a laTargetTransform, y 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))Establece la
Rotational resultado deMakeShortestRotationBetween(), pasando la rotación de la transformación original y la transformación original rotada por laRotationToApply.VerseTranslation := Lerp(OriginalTransform.Translation, TargetTransform.Translation, (TotalTime * RotationRate) / (TotalRotations)) Rotation := MakeShortestRotationBetween(OriginalTransform.Rotation, OriginalTransform.Rotation.RotateBy(RotationToApply))~~~Ajusta la
Scaleal resultado de llamar aLerp()entre laOriginalTransform.Scaley laTargetTransform.Scale. Ten en cuenta que esta es la escala a la que debería escalar el elemento, no la cantidad por la que tendría que escalar. TuEndTransformcompleto debería tener el siguiente aspecto: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)
Con la transformación final establecida, ¡es hora de construir un fotograma clave! En gran parte, se trata del mismo proceso que realizaste para la función
MoveToEase(). Crea una nueva variablekeyframe_deltacon el nombreKeyFrame. Establece el valorDeltaLocationcomo la diferencia entre las traslaciones final e inicial de la transformación. EstableceDeltaRotationen la rotación de la transformación final. Como necesitas calcular el cambio de escala, establece el valorDeltaScalecomo el resultado de dividir la escala de la transformación final por la escala de la transformación inicial. ElTimedebería ser elAnimationTime, y elInterpolationTypedebería ser el resultado de una expresiónif. SiUseEasePerKeyframeestá activado, utilizaMoveEaseType. De lo contrario, utiliza el tipo lineal. Tu expresión de fotogramas clave debería tener el siguiente aspecto: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:Con el fotograma clave construido, ahora puedes añadirlo a la matriz
Keyframes. Después, establece laStartTransformenEndTransformpara actualizarla para el siguiente fotograma clave. Por último, si elTotalTimees ahora mayor que elMoveDuration, sal del bucle.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: breakExiste un caso extremo importante que hay que tener en cuenta: ¿qué ocurre cuando se necesita hacer menos de una rotación completa? Como estás añadiendo el
TimePerRotationaTotalTime, esto quiere decir que elTotalTimepodría ser mayor que laMoveDurational inicio del bucle. En este caso, tendrás que gestionar el tiempo que sobra y hacer una rotación inferior a la completa, con un tiempo de animación más corto para compensar la diferencia. Sigue estos pasos para tener en cuenta este caso:Al principio del bucle, después de actualizar
TotalTime, inicia una expresiónif. Dentro, inicializa una variableLeftoverTime,y establécela igual al resultado de restarTotalTimeyMoveDuration,comprobando si es mayor que0.0. Esta expresión solo asignaráLeftoverTimesi la comparación da como resultado true.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.0Para saber qué fracción de rotación tienes que hacer, inicializa una nueva variable
Rotation Fractiony establécela igual al resultado de tomar la diferencia entreTimePerRotationyLeftoverTime, todo dividido porTimePerRotation.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)/TimePerRotationPara crear una rotación modificada a partir de
RotationFraction, deberás utilizarSlerp[]. Se trata de la versión deLerp()que gestiona la interpolación esférica y tiene parámetros similares. Esta función encuentra la rotación más corta entre dos rotaciones diferentes y devuelve una rotación basada en el parámetro de interpolación lineal. Llama aSlerp[], interpolando entre laIdentityRotation()y laIdentityRotation()rotada porRotationToApply, utilizando laRotationFractioncomo parámetro de interpolación lineal. Aquí estás utilizandoIdentityRotation()porque solo te interesa encontrar qué rotación fraccional necesitas aplicar, no en qué rotación final debería estar laEndTransform.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 interpolationCon esos valores configurados, establece la
RotationToApplyenModifiedRotation, multiplica elAnimationTimepor laRotationFractionpara saber cuánto acortar la animación y, finalmente, establece elTotalTimeenMoveDuration, ya que no quieres que sea mayor que ese valor cuando calcules laEndTransform.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 final de la función, después del bucle, devuelve la matriz
Keyframes. Tu funciónBuildMovingAnimationKeyframes()completa debería tener el siguiente aspecto: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 theAhora que has definido la lógica para construir los fotogramas clave, ha llegado el momento de animarlos. Utilizarás una función separada para construir y llamar a la animación. Añade una nueva función
BuildAndPlayAnimation()a tu claseanimating_prop. Añade el modificador<suspends>a esta función para que pueda llamar a otras funciones asíncronas.Verse# Builds an animation from an array of keyframes, then calls MoveToEase() # to animate the prop. BuildAndPlayAnimation()<suspends>:void=En
BuildAndPlayAnimation(), inicializa una nueva matrizkeyframe_deltacon el nombreKeyframes. Después, estableceKeyframesal resultado de llamar aBuildMovingAnimationKeyframes(). UtilizaRootProp.GetTransform()como transformación inicial, ya que la posición del elemento cambiará entre llamadas aMove(). Inicializa una variableanimation_modeaanimation_mode.OneShoty llama aMoveToEase(), pasando la matrizKeyframesyAnimationMode.Tu función
BuildAndPlayAnimation()completa debería tener el siguiente aspecto: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.OneShotEn
Move(), llama aBuildAndPlayAnimation()después de establecerTargetTransformen la transformación del objetivo de movimiento.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()
Hay que tener en cuenta un caso más. ¿Qué pasa si no estableces ningún objetivo de movimiento? En este caso, el elemento debería seguir girando en su sitio, sin desplazarse a un nuevo destino. Para controlarlo, añade una expresión if en la parte superior de tu función Move(). En el if, comprueba si MoveTargets.Length = 0 y, de ser así, establece TargetTransform a la transformación del elemento raíz. Luego llama a BuildAndPlayAnimation(). De este modo, tu elemento seguirá animándose incluso si no has establecido un objetivo de movimiento. Tu animación Move() completa debería tener el siguiente aspecto:
# 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()
Ahora tienes que hacer referencia a animating_prop en tu clase prop_animator. En prop_animator, añade una matriz editable de animating_prop con el nombre MoveAndRotateProps. En OnBegin(), en otra expresión for, inicializa cada elemento en MoveAndRotateProps llamando a Setup(). Tu clase prop_animator completa debería tener el siguiente aspecto:
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.
Guarda el código y compílalo.
¡Enhorabuena! ¡Ya tienes todo el código! Ahora ha llegado el momento de conectarlo todo.
La clase animating_prop que acabas de crear sirve para mover, rotar y escalar elementos. No obstante, sigue dependiendo de la clase moveable_prop, ya que necesita heredar varias funciones como ManageMovement(). Dado que la clase animating_prop puede realizar los tres tipos de movimiento, puede resultarte útil refactorizar animating_prop para incluir toda la lógica de moveable_prop y así la clase pueda funcionar de forma independiente. Aquí se incluye un ejemplo de refactorización, que fusiona animating_prop y moveable_prop en un único archivo. También incluye la clase de dispositivo de Verse prop_animator. Todavía necesitarás la funcionalidad de movement_behaviors para que el código se ejecute, pero esta refactorización reduce el número de archivos necesarios de cinco a dos. Este código también se incluye en la sección Código 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."
Cómo vincular elementos a dispositivos
De vuelta en el editor, elimina una sección del recorrido después de la sección de elementos que giran para crear un espacio antes del objetivo final. Añade a tu nivel otra barra giratoria doble (pequeña) FG01 y una plataforma flotante (mediana) FG01. Nómbralas SpinningMovingBar y TranslatingPlatform y después añade varios elementos bombilla de botón FG01, que serán los objetivos a los que se moverá cada elemento. Dales el nombre PlatformTarget. Coloca las plataformas y la barra sobre el espacio y asegúrate de colocar los objetivos donde quieres que vayan las plataformas. En este ejemplo, la barra giratoria se mueve de lado a lado y la plataforma se mueve hacia delante y hacia atrás.
Configuración de la barra giratoria y la plataforma móvil. Las flechas indican en qué direcciones se mueve cada elemento. Tanto la barra giratoria como la plataforma se mueven hacia delante y hacia atrás, y la barra gira mientras se mueve.
Selecciona el animador de tu elemento en el esquematizador. Añade un elemento de matriz a AnimatingProps para tu barra giratoria. Establece cada valor de la siguiente manera:
| Opción | Value | Explicación |
|---|---|---|
Rotación adicional | 90.0 | Este elemento hará una rotación de 90 grados cada vez. |
Tasa de rotación | 1.5 | Este elemento hará una rotación cada |
Utilizar aceleración por fotograma clave | false | Esto utilizará el tipo de aceleración lineal en cada fotograma clave para mover y rotar el elemento a una velocidad uniforme. |
MoveTargets | 2 elementos, asignados a objetivos de plataforma. | Estos son los objetivos a los que quieres que se mueva la barra. |
RootProp | SpinningMovingBar | Este es el elemento que estás animando. |
Añade otro elemento de matriz a TranslatingProps para la plataforma móvil. Asigna MoveTargets a tus objetivos de plataforma, y RootProp a tu TranslatingPlatform.
Pulsa Abrir sesión e intenta recorrer tu carrera de obstáculos completa.
Por tu cuenta
¡Y ya está! Ahora tienes todo lo que necesitas para hacer tu propia carrera de obstáculos de Fall Guys con Verse.
Puedes utilizar el código para animar elementos del modo Creativo en cualquiera de tus experiencias, ¡e incluso más allá de los proyectos de Fall Guys!
Con lo que has aprendido, intenta lo siguiente:
Crea obstáculos que giren en varias direcciones, o que giren aleatoriamente a lo largo de los fotogramas clave.
Crea obstáculos que solo se activen cuando un jugador se pare sobre ellos o se acerque a cierta distancia.
Descubre cómo hacer plataformas que desaparezcan después de cierto tiempo, o que lleven al jugador a posiciones peligrosas si permanece demasiado tiempo en ellas.
Código completo
A continuación encontrarás el código completo creado en esta sección, incluido un ejemplo de refactorización para 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 (ejemplo de refactorización de 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."