El paso previo a los objetos que se mueven, rotan o escalan es hacer las tres cosas simultáneamente. Sin embargo, hay que tomar en cuenta algunos desafíos importantes al crear animaciones para las utilerías que se mueven de varias maneras al mismo tiempo.
Dado que el controlador de animación solo puede reproducir una animación a la vez, no puedes mover, rotar y escalar en animaciones separadas. Estas animaciones también necesitan varios fotogramas clave, ya que podrías querer rotar una utilería varias veces por animación. Puesto que necesitas crear todos los fotogramas clave de antemano, también necesitas calcular la posición, la rotación y la escala en cada punto del trayecto de la utilería. ¿Qué sucede si la utilería no hace una cantidad uniforme de rotaciones? ¿Cómo controlas media rotación?
Se utilizará mucha matemática en la próxima sección, pero, al final, podrás mover, rotar y escalar utilerías a diferentes puntos, y crear desafíos de plataforma complejos, dinámicos y (¡más importante aún!) muy divertidos para hacer la pista de Fall Guys de tus sueños.
Cómo crear animaciones que se muevan, roten y se escalen
Sigue estos pasos para comenzar a armar todo:
Crea una nueva clase de Verse llamada
animating_propque herede demovable_propusando Verse Explorer. 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):Agrega las instrucciones
que usen { /Fortnite.com/Devices/CreativeAnimation }yque usen { /UnrealEngine.com/Temporary/SpatialMath }en la parte superior del archivo para importar estos módulos. Los necesitarás para animar tu utilería. Los textos emergentes que se usan en esta sección también se incluyen aquí.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
rotacióneditable denominadaAdditionalRotation. Esta es la rotación que se aplicará aRootProppor fotograma clave.Verse# The additional rotation to apply to the RootProp per keyframe. @editable {ToolTip := AdditionalRotationTip} AdditionalRotation:rotation = rotation{}Un
floateditable denominadoRotationRate. Esta es la cantidad de tiempo que lleva hacer unaAdditionalRotation, en segundos.Verse# The time it takes to make one AdditionalRotation in seconds. @editable {ToolTip := RotationRateTip} var RotationRate:float = 1.0Una
lógicaeditable denominadaUseEasePerKeyFrame. Esto establece si cada fotograma clave usa elMoveEaseTypepara la interpolación. En este ejemplo, si se establece esto enfalse, se usará por defecto 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_propdenominadaMoveTargets. Estas son las diferentes utilerías del modo Creativo hacia las que viajará tu utilería raíz.Verse# The Creative prop target for the RootProp to move toward. @editable {ToolTip := MoveTargetsTip} var MoveTargets:[]creative_prop = array{}Una variable
transformdenominadaTargetTransform.Esta es la transformación a la que está viajando actualmente tu utilería raíz.Verse# The transform the prop is currently targeting. var TargetTransform:transform = transform{}
La definición de la clase debería verse así:
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. Luego, en una expresiónfor, itera a través de cadaMoveTargeten la matrizMoveTargets. Comprueba si cadaMoveTargetes válido y, de ser así, estableceTargetTransformen la transformación deMoveTarget.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.De vuelta en tu archivo
movement_behaviors, añade un nuevo método llamadoBuildMovingAnimationKeyframes(). Esta función creará y devolverá una matriz de fotogramas clave que animan una utilería moviéndose y rotando hacia una transformación objetivo. Esta función toma varios parámetros deanimating_prop:MoveDuration,RotationRate,AdditionalRotation,OriginalTransform(la transformación inicial de la utilería),TargetTransform,MoveEaseTypey un nuevo valorlógicollamadoUseEasePerKeyframe. Esto determina si utilizasMoveEaseTypepara cada fotograma clave. La firma de tu función debería verse así: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
floatllamadaTotalTime. Este es el tiempo total que se ha pasado animando hasta el momento.Verse# The total amount of time spent animating. var TotalTime:float = 0.0Dos variables
transformllamadasStartTransformyEndTransform. Estas son las transformaciones iniciales y finales de la utilería al inicio y al final de cada fotograma clave. Inicializa ambos enOriginalTransform.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
rotaciónvariable denominadaRotationToApply, inicializada enAdditionalRotation. Esta es la rotación real que aplicarás a la utilería para cada fotograma clave. Por lo general, este seráAdditionalRotation, pero si necesitas hacer una rotación fraccionaria, cambiarás 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
floatllamadaAnimationTime. Este es el tiempo en segundos que demora cada fotograma clave. Inicialízala en1.0 / RotationRate, ya que la RootProp debe hacer un númeroRotationRatede rotaciones por 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
floatllamadoTotalRotations. Este es el número total de rotaciones que se hará en toda la animación, y se inicializa conMoveDuration * RotationRate. El motivo por el que es unfloaty no unintes para ocuparse de 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
floatdenominadoTimePerRotation. Este es el tiempo en segundos que tarda una rotación en completarse. Ahora, tu función debería verse así.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
Son muchos valores de los que hacer un seguimiento, así que hagamos un cálculo de ejemplo, usando 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 un RotationRate de 2.5 y un MoveDuration de 5.0, realizarás 12.5 rotaciones en total, y cada rotación tardará 0.4 segundos. Esto significa que tendrás que hacer media rotación adicional al final de la animación. Quizás también hayas notado que el tiempo de animación y el tiempo por rotación son los mismos. Este casi siempre es así, excepto cuando necesitas hacer una rotación incompleta. Aunque inicialmente tienen el mismo valor, debes monitorear ambas variables para encargarte de algunos cálculos matemáticos más adelante.
Cómo crear fotogramas clave en un bucle
¡Es hora de crear! Sigue estos pasos para crear un bucle que construye fotogramas clave.
Agrega una expresión
loopaBuildMovingAnimationKeyframes().En cada iteración del bucle, crearás un nuevo fotograma clave y lo añadirás a la matriz de fotogramas clave. Al comienzo del bucle, actualizaTotalTimeconTimePerRotation.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 += TimePerRotationConstruye el
EndTransform, que es donde debería estar la utilería al final de este fotograma clave. Establece laEndTransformen una nueva transformación con los siguientes parámetros:Establece la
Translationen el resultado de llamar aLerp()entre laOriginalTransformy laTargetTransform. La funciónLerp()toma dos valores y una relación Lerp entre0.0y1.0. Luego genera un nuevo valor entre estos dos números con base en el índice de lerp. Cuanto más cerca esté el índice de lerp de 1.0, más cercana estará la transformación deTargetTransformy 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
Rotationen el resultado deMakeShortestRotationBetween()al pasar 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))~~~Establece la
Escalaal resultado de llamar aLerp()entreOriginalTransform.ScaleyTargetTransform.Scale. Ten en cuenta que esta es la escala a la que debería escalarse la utilería, no la cantidad por la que necesita escalarse. TuEndTransform completodebería verse así: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)
Ya con la transformación final lista, es hora de crear un fotograma clave. En gran parte, este es el mismo proceso que seguiste para tu función
MoveToEase(). Crea una nueva variablekeyframe_deltallamadaKeyFrame. Establece laDeltaLocationen la diferencia entre las traslaciones de la transformación inicial y final. Establece laDeltaRotationen la rotación de la transformación final. Ya que necesitas calcular el cambio en la escala, establece laDeltaScaleen el resultado de dividir la escala de la transformación final por la escala de la transformación inicial. ElTimedebe ser elAnimationTime, y elInterpolationTypedebe ser el resultado de una expresiónif. SiUseEasePerKeyframees verdadero, usaMoveEaseType. De lo contrario, usa el tipo lineal. Tu expresión del fotograma clave debería verse así: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 tu fotograma clave construido, ahora puedes añadirlo a la matriz
Keyframes. Luego, estableceStartTransformenEndTransformpara actualizarlo para el siguiente fotograma clave. Finalmente, si elTotalTimeahora es mayor que laMoveDuration, 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: breakHay una situación límite importante que se debe tener en cuenta: ¿qué sucede cuando necesitas hacer menos de una rotación completa? Dado que estás añadiendo el
TimePerRotationalTotalTime, esto significa que elTotalTimepodría ser mayor que laMoveDurational inicio del bucle. En esta situación, debes manejar el tiempo restante y hacer una rotación incompleta con un tiempo de animación más corto para contrarrestar la diferencia. Sigue estos pasos para contrarrestar esta situación:De vuelta al inicio del bucle, después de actualizar
TotalTime, comienza una expresiónif. Adentro, inicializa una variableLeftoverTimey establécela igual al resultado de restarTotalTimeyMoveDurationy verifica si es mayor que0.0. Esta expresión solo asignaráLeftoverTimesi la comparación es verdadera.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 una rotación necesitas hacer, inicializa una nueva variable
RoationFraction, y defínela igual a 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, usarásSlerp[]. Esta es la versión deLerp()que controla la interpolación esférica y tiene parámetros similares. Encuentra la rotación más corta entre dos rotaciones diferentes, y devuelve una rotación con base en el parámetro de lerp. Llama aSlerp[], interpolando entreIdentityRotation()eIdentityRotation()rotados porRotationToApply, utilizandoRotationFractioncomo parámetro lerp. Estás usandoIdentityRotation()aquí porque solo te interesa encontrar qué rotación fraccionaria debes aplicar, no la rotación final en la que 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 estos valores ya establecidos, establece la
RotationToApplyen laModifiedRotation, multiplica elAnimationTimepor laRotationFractionpara saber cuánto acortar tu animación y, finalmente, establece elTotalTimeen laMoveDuration, ya que no quieres que sea mayor que este valor al calcular 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 tu función, después del bucle, devuelve la matriz
Keyframes. Tu funciónBuildMovingAnimationKeyframes()completa debería verse así: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 definiste la lógica para construir tus fotogramas clave, es hora de animarlos. Usarás una función aparte para crear y llamar a tu animación. Incluye una nueva función
BuildAndPlayAnimation()en tu claseanimating_prop. Agrega el modificador<suspends>a esta función para permitirle 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_deltadenominadaKeyframes. Luego, establezcaKeyframesen el resultado de llamar aBuildMovingAnimationKeyframes(). UtilizaRootProp.GetTransform()como transformación inicial, ya que la posición de la utilería cambiará entre llamadas aMove(). Inicializa una variableanimation_modeenanimation_mode.OneShoty llama aMoveToEase()pasándole la matrizKeyframesy elAnimationMode.Tu función BuildAndPlayAnimation() completa debería verse así: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.OneShotDe vuelta en
Move(), llamar aBuildAndPlayAnimation()después de definirTargetTransforma la transformar de objetivos 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 un caso más para considerar. ¿Qué debería pasar si no estableces ningún objetivo de movimiento? En esta situación, tu utilería debería seguir rotando en el lugar, sin moverse a un nuevo destino. Para manejar esto, añade una expresión if a la parte superior de tu función Move(). En el if, verifica si MoveTargets.Length = 0 y, de ser así, establece la TargetTransform en la transformación de la utilería raíz. Luego, llamar a BuildAndPlayAnimation(). De esta manera, tu utilería seguirá animándose incluso si no estableciste un objetivo de movimiento. Tu animación Move() completa debería verse así:
# 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 necesitas hacer referencia a animating_prop en tu clase prop_animator. En prop_animator, agrega una matriz editable de animating_prop denominada MoveAndRotateProps. En OnBegin(), en otra expresión for , inicializa cada utilería en MoveAndRotateProps al llamar a Setup(). Tu clase prop_animator completa debería verse así:
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 tu código y compílalo.
¡Felicidades, esa es toda la parte del código! Ahora, es momento de conectar todo.
La clase animating_prop que acabas de crear puede mover, rotar y escalar utilerías. Sin embargo, todavía depende de la clase moveable_prop porque necesita heredar varias funciones como ManageMovement(). Dado que la clase animating_prop puede llevar a cabo los tres tipos de movimiento, puede ser útil refactorizar animating_prop para que incluya toda la lógica de moveable_prop y, de este modo, la clase pueda ser independiente. Aquí se incluye un ejemplo de refactorizar, que fusiona animating_prop y moveable_prop en un solo archivo. También incluye la clase de dispositivo de verso prop_animator. Todavía necesitarás la funcionalidad de movement_behaviors para que tu código se ejecute, pero esta refactorización reduce la cantidad 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 utilerías a dispositivos
De vuelta en el editor, elimina una sección de la pista después de la sección de las utilerías rotatorias para crear una brecha antes de la meta. Añade otro FG01 SpinningBar Double S y FG01 Hover Platform M a tu nivel. Nómbralas SpinningMovingBar y TranslatingPlatform, luego añade varias utilerías de bombilla de botón FG01, que serán los objetivos a los que se moverá cada utilería. Llama a estos PlatformTarget. Pon las plataformas y la barra sobre la brecha y asegúrate de poner los objetivos adonde quieres que se muevan las plataformas. En este ejemplo, la barra giratoria se mueve de lado a lado, mientras que la plataforma se mueve hacia adelante y hacia atrás.
Configuración de la barra giratoria y la plataforma móvil. Las flechas indican en qué dirección se mueve cada utilería. Tanto la barra giratoria como la plataforma se mueven hacia adelante y hacia atrás, y la barra giratoria gira mientras se mueve.
Selecciona tu animador de utilería en el esquematizador. Agrega un elemento de matriz a AnimatingProps para tu barra giratoria. Establece cada valor en lo siguiente:
| Opción | Valor | Explicación |
|---|---|---|
Rotación adicional | 90.0 | Esta utilería hará una rotación de 90 grados cada vez. |
Tasa de rotación | 1.5 | Esta utilería hará una rotación cada |
Usar suavizado por fotograma clave | false | Esto usará el tipo de suavizado lineal en cada fotograma clave para mover y rotar la utilería a una velocidad constante. |
MoveTargets | 2 elementos, asignados a objetivos de plataforma. | Estos son los Dispara aquí a los que deseas que se mueva la barra. |
RootProp | SpinningMovingBar | Esta es la utilería que estás animando. |
Agrega otro elemento de matriz a TranslatingProps para tu plataforma móvil. Asigna MoveTargets a tus objetivos de plataforma y RootProp a tu TranslatingPlatform.
Presiona Comenzar sesión e intenta correr a través de toda la pista de obstáculos.
Por tu cuenta
¡Y eso es todo! Ahora tienes todo lo que necesitas para hacer tu propia pista de obstáculos de Fall Guys usando Verse.
Puedes usar este código para animar utilerías del modo Creativo en cualquiera de tus experiencias, e incluso más allá de proyectos de Fall Guys.
Con lo que has aprendido, intenta lo siguiente:
Crea obstáculos que giren en una variedad de direcciones o que giren aleatoriamente a lo largo de fotogramas clave.
Crea obstáculos que se activen solo cuando un jugador se pare sobre ellos o esté a cierta distancia.
Descubre cómo hacer plataformas que desaparezcan después de un tiempo determinado, o mover al jugador a posiciones peligrosas si permanecen demasiado tiempo.
Código completo
Este es el código completo compilado en esta sección, incluido un refactor de ejemplo para animating_prop .
movible_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):
giratorio_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."