Mover entidades

Cómo mover, rotar y escalar una entidad gradualmente a lo largo del tiempo, con cambios incrementales.

Para mover, rotar o cambiar el tamaño de una entidad en tu escena durante un periodo de tiempo, usa el Tween componente. El engine realiza la transformación deseada de forma suave, mostrando actualizaciones en cada frame hasta que termina la duración especificada. Además, los Transform valores del componente de la entidad afectada se actualizan en tiempo real en caso de que sea necesario hacer comprobaciones de proximidad en el código de la escena.

circle-info

💡 Consejo: En el Scene Editor in Creator Hubarrow-up-right, puedes mover entidades de forma no-code vía Actions, véase Make any item smartarrow-up-right.

El componente Tween tiene las siguientes funciones:

  • setMove: Mover entre dos puntos

  • setRotate: Rotar entre dos direcciones

  • setScale: Escalar entre dos tamaños

  • setMoveContinuous: Moverse constantemente en la misma dirección

  • setRotateContinuous: Rotar constantemente en la misma dirección

  • setTextureMove: Desplazar la textura de un material entre dos posiciones

  • setTextureMoveContinuous: Desplazar la textura de un material constantemente en la misma dirección

Mover entre dos puntos

Para mover una entidad entre dos puntos, crea un Tween componente con la setMove .

const myEntity = engine.addEntity()
Transform.create(myEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(myEntity)

Tween.setMove(myEntity, 
	Vector3.create(1, 1, 1), 
	Vector3.create(8, 1, 8), 
	2000
)

El tween de movimiento requiere la siguiente información:

  • entity: La entidad a mover

  • start: Un Vector3 para la posición inicial

  • end: Un Vector3 para la posición final

  • duration: Cuántos milisegundos toma moverse entre las dos posiciones

Estos otros parámetros opcionales también están disponibles:

  • faceDirection: Si es true, la entidad se rota para mirar en la dirección del movimiento.

  • easingFunction: Qué función de easing usar. Ver Non-linear tweens

Rotar entre dos direcciones

Para rotar una entidad entre dos puntos, crea un Tween componente con la setRotate .

El tween de rotación requiere la siguiente información:

  • start: Un Quaternion para la rotación inicial

  • end: Un Quaternion para la rotación final

  • duration: Cuántos milisegundos toma moverse entre las dos posiciones

Este otro parámetro opcional también está disponible:

Rotar con un punto de pivote

Al rotar una entidad, la rotación siempre se hace en referencia a la coordenada central de la entidad. Para rotar una entidad usando otro conjunto de coordenadas como punto de pivote, crea una segunda entidad (invisible) con el punto de pivote como su posición y hazla padre de la entidad que quieres rotar.

Al rotar la entidad padre, sus hijos serán todos rotados usando la posición del padre como punto de pivote. Ten en cuenta que la position de la entidad hija está en referencia a la del padre.

Ten en cuenta que en este ejemplo, el sistema está rotando la pivotEntity entidad, que es padre de la childEntity entidad.

Escalar entre dos tamaños

Para cambiar la escala de una entidad entre dos tamaños, crea un Tween componente con su modo ajustado a Tween.Mode.Scale.

El tween de escala requiere la siguiente información:

  • start: Un Vector3 para el tamaño inicial

  • end: Un Vector3 para el tamaño final

  • duration: Cuántos milisegundos toma moverse entre las dos posiciones

Este otro parámetro opcional también está disponible:

Non-linear tweens

Los tweens pueden seguir diferentes Easing Functions que afectan la tasa de cambio a lo largo del tiempo. Una linear función, significa que la velocidad del cambio es constante desde el inicio hasta el final. Hay muchas opciones para elegir, que trazan curvas de formas diferentes dependiendo de si el comienzo y/o el final empiezan lento, y cuánto. Una easeinexpo curva comienza lenta y termina rápida, incrementando la velocidad exponencialmente, por el contrario una easeoutexpo curva comienza rápida y termina lenta.

circle-info

💡 Consejo: Experimenta con diferentes curvas de movimiento. Las diferencias suelen ser sutiles, pero subconscientemente interpretamos información por cómo se mueven las cosas, como peso, fricción o incluso personalidad.

El opcional easingFunction parámetro toma su valor del EasingFunction enum, que ofrece las siguientes opciones:

  • EF_EASEBACK

  • EF_EASEBOUNCE

  • EF_EASECIRC

  • EF_EASECUBIC

  • EF_EASEELASTIC

  • EF_EASEEXPO

  • EF_EASEINBACK

  • EF_EASEINBOUNCE

  • EF_EASEINCIRC

  • EF_EASEINCUBIC

  • EF_EASEINELASTIC

  • EF_EASEINEXPO

  • EF_EASEINQUAD

  • EF_EASEINQUART

  • EF_EASEINQUINT

  • EF_EASEINSINE

  • EF_EASEOUTBACK

  • EF_EASEOUTBOUNCE

  • EF_EASEOUTCIRC

  • EF_EASEOUTCUBIC

  • EF_EASEOUTELASTIC

  • EF_EASEOUTEXPO

  • EF_EASEOUTQUAD

  • EF_EASEOUTQUART

  • EF_EASEOUTQUINT

  • EF_EASEOUTSINE

  • EF_EASEQUAD

  • EF_EASEQUART

  • EF_EASEQUINT

  • EF_EASESINE

  • EF_LINEAR

Rotación constante

Para hacer que una entidad rote constantemente, usa el Tween componente con la setRotateContinuous .

El tween de rotación continua requiere la siguiente información:

  • entity: La entidad a rotar

  • direction: Un Quaternion para la rotación

  • Cambia la velocidad a la que se reproduce una animación cambiando la propiedad: Cuántos grados por segundo rotará la entidad

Este otro parámetro opcional también está disponible:

  • duration: Cuántos milisegundos sostener la rotación. Después de este tiempo, la rotación se detendrá.

Movimiento constante

Para hacer que una entidad se mueva constantemente en la misma dirección, usa el Tween componente con la setMoveContinuous .

El tween de movimiento continuo requiere la siguiente información:

  • entity: La entidad a mover

  • direction: Un Vector3 para el movimiento

  • Cambia la velocidad a la que se reproduce una animación cambiando la propiedad: Cuántos metros por segundo se moverá la entidad

Este otro parámetro opcional también está disponible:

  • duration: Cuántos milisegundos sostener el movimiento. Después de este tiempo, el movimiento se detendrá.

El tween de movimiento continuo requiere la siguiente información:

Secuencias de Tween

Para hacer que una entidad reproduzca una serie de tweens en secuencia, usa el TweenSequence componente. Este componente requiere dos campos:

  • sequence: Un array con múltiples definiciones de tween, que se ejecutarán secuencialmente. El array puede estar vacío, en cuyo caso solo reproduce el tween actual.

  • loop (opcional): Si no se proporciona, la secuencia solo se reproduce una vez. Si el campo está presente, el valor debe ser un valor del TweenLoop enum. Los valores aceptados son:

    • TL_RESTART: Cuando la secuencia termina, se reinicia. Si el último estado no coincide con el primer estado, la entidad salta instantáneamente de uno a otro.

    • TL_YOYO: Cuando la secuencia termina, va hacia atrás, realizando todos los tweens en reversa hasta que alcanza el inicio nuevamente. Luego comienza otra vez.

Mover de ida y vuelta

Para hacer que una plataforma se mueva constantemente de ida y vuelta entre dos posiciones, deja el sequence array vacío, y establece loop a TweenLoop.TL_YOYO

La entidad se moverá de ida y vuelta entre el punto inicial y el punto final, con la misma duración y la misma función de easing en ambas direcciones.

Seguir un camino

Para hacer que una entidad siga un camino más complejo con múltiples puntos, proporciona una lista de definiciones de tween en la sequence de un TweenSequence componente.

Ten en cuenta que al definir un tween dentro de un TweenSequence, necesitas usar el formato más verboso de Tween.Mode.Move, o Tween.Mode.Rotate, o Tween.Mode.Scale para definir el tween. En este formato más verboso, necesitas especificar:

  • duration: Cuántos milisegundos toma moverse entre las dos posiciones

  • easingFunction: Qué función de easing usar. Ver Non-linear tweens. En este formato el valor es requerido.

  • mode: El modo del tween, que puede ser Tween.Mode.Move, Tween.Mode.Rotate, o Tween.Mode.Scale.

Y dentro del campo mode debes especificar:

  • start: El valor inicial del tween

  • end: El valor final del tween

Al finalizar un tween

Usa tweenSystem.tweenCompleted para detectar cuando un tween ha terminado. Esto puede ser útil para realizar acciones cuando un tween termina, por ejemplo para abrir una puerta de ascensor.

Tweens simultáneos

Una entidad solo puede tener un Tween componente, y cada componente tween solo puede realizar una transformación a la vez. Por ejemplo, no puedes hacer que una entidad se mueva lateralmente y además rote al mismo tiempo. Como solución alternativa, puedes usar entidades con parent. Por ejemplo, puedes tener una entidad padre invisible que se mueva lateralmente, con una hija visible que rote.

En el siguiente fragmento, una entidad padre rota mientras una hija aumenta su escala.

Pausar un tween

Para pausar un tween, cambia la detiene todas las demás animaciones que la entidad está reproduciendo actualmente. Para reproducir múltiples animaciones al mismo tiempo, modifica manualmente la propiedad propiedad a false. Para reanudarlo, cámbiala de nuevo a true.

Para terminar un tween que no necesita ser continuado, elimina el Tween componente de la entidad. Si la entidad también estaba usando un TweenSequence componente, elimínalo también.

Tweens basados en un sistema

En lugar de usar el componente Tween y dejar que el engine maneje la transformación, puede que prefieras hacer esta transición de forma incremental, frame por frame, vía un systemarrow-up-right en tu escena. Moviendo la entidad una pequeña cantidad cada vez que la función se ejecuta.

Por un lado, esto te da más control para recalcular movimientos en cada frame. Por otro lado, el código es más complicado, y los jugadores con máquinas menos potentes podrían experimentar el tween como entrecortado, notando cada incremento.

Mover vía system

La forma más fácil de mover una entidad es modificar gradualmente el position valor almacenado en el Transform componente.

En este ejemplo estamos moviendo una entidad 0.1 metros por tick del game loop.

Vector3.Forward() retorna un vector que apunta hacia adelante y mide 1 metro de longitud. En este ejemplo luego escalamos este vector a 1/10 de su longitud con Vector3.scale(). Si nuestra escena tiene 30 frames por segundo, la entidad se está moviendo a 3 metros por segundo de velocidad.



Rotar vía system

La forma más fácil de rotar una entidad es cambiar gradualmente los valores en el componente Transform de forma incremental, y ejecutar esto como parte de la función de un system.

Ten en cuenta que para combinar la rotación actual con cada incremento, estamos usando Quaternion.multiply. En matemática de quaterniones, combinas dos rotaciones multiplicándolas, NO sumándolas. La rotación resultante de multiplicar un quaternion por otro será la rotación final equivalente tras realizar primero una rotación y luego la otra.

En este ejemplo, estamos rotando la entidad 1 grado en dirección hacia arriba en cada tick del game loop.

circle-info

💡 Consejo: Para hacer que una entidad siempre rote para mirar al jugador, puedes añadir un Billboard componentearrow-up-right.



Rotar vía system sobre un punto de pivote

Al rotar una entidad, la rotación siempre se hace en referencia a la coordenada central de la entidad. Para rotar una entidad usando otro conjunto de coordenadas como punto de pivote, crea una segunda entidad (invisible) con el punto de pivote como su posición y hazla padre de la entidad que quieres rotar.

Al rotar la entidad padre, sus hijos serán todos rotados usando la posición del padre como punto de pivote. Ten en cuenta que la position de la entidad hija está en referencia a la del padre.

Ten en cuenta que en este ejemplo, el sistema está rotando la pivotEntity entidad, que es padre de la childEntity entidad.



Ajustar movimiento al tiempo de retardo

Supón que el jugador que visita tu escena tiene dificultades para seguir el ritmo del frame rate. Eso podría resultar en que el movimiento parezca entrecortado, ya que no todos los frames están uniformemente temporizados pero cada uno mueve la entidad en la misma cantidad.

Puedes compensar este desfase en el tiempo usando el dt parámetro para ajustar la escala del movimiento.

El ejemplo anterior mantiene el movimiento aproximadamente a la misma velocidad que el ejemplo de movimiento anterior, incluso si el frame rate baja. Cuando se ejecuta a 30 frames por segundo, el valor de dt es 1/30.

También puedes suavizar rotaciones de la misma manera multiplicando la cantidad de rotación por dt.

Mover entre dos puntos vía system

Si quieres que una entidad se mueva suavemente entre dos puntos, usa el lerp (interpolación lineal) algoritmo. Este algoritmo es muy conocido en desarrollo de juegos, ya que es realmente útil.

El lerp() la función toma tres parámetros:

  • El vector para la posición de origen

  • El vector para la posición objetivo

  • La cantidad, un valor de 0 a 1 que representa qué fracción de la traducción realizar.

El algoritmo de interpolación lineal encuentra un punto intermedio en el camino entre ambos vectores que coincide con la cantidad provista.

Por ejemplo, si el vector de origen es (0, 0, 0) y el vector objetivo es (10, 0, 10):

  • Usar una cantidad de 0 devolvería (0, 0, 0)

  • Usar una cantidad de 0.3 devolvería (3, 0, 3)

  • Usar una cantidad de 1 devolvería (10, 0, 10)

Para implementar esto lerp() en tu escena, recomendamos crear un custom componentarrow-up-right para almacenar la información necesaria. También necesitas definir un sistema que implemente el movimiento gradual en cada frame.



Rotar entre dos ángulos vía system

Para rotar suavemente entre dos ángulos, usa el slerp (esférica (interpolación) lineal). Este algoritmo es muy similar a un lerp, pero maneja rotaciones en quaternion.

El slerp() la función toma tres parámetros:

circle-info

💡 Consejo: Puedes pasar valores de rotación en eulerarrow-up-right grados (de 0 a 360) usando Quaternion.fromEulerDegrees().

Para implementar esto en tu escena, recomendamos almacenar los datos que entran en la Slerp() función en un custom componentarrow-up-right. También necesitas definir un sistema que implemente la rotación gradual en cada frame.

circle-exclamation


Un enfoque más simple pero menos eficiente aprovecha la Quaternion.rotateTowards función, y evita usar cualquier componente personalizado.

En el ejemplo anterior Quaternion.rotateTowards toma tres argumentos: la rotación inicial, la rotación final deseada y el incremento máximo por frame. En este caso, dado que el incremento máximo es de dt * 10 grados, la rotación se realizará durante un periodo de un par de 9 segundos.

Ten en cuenta que el sistema también comprueba si la rotación está completa y si es así elimina el system del engine. De otro modo, el sistema seguiría haciendo cálculos en cada frame, incluso una vez la rotación esté completa.

Cambiar escala entre dos tamaños vía system

Si quieres que una entidad cambie de tamaño suavemente y sin cambiar sus proporciones, usa la lerp (interpolación lineal) algoritmo de la Scalar objeto.

De lo contrario, si quieres cambiar los ejes en diferentes proporciones, usa Vector3 para representar la escala de origen y la escala objetivo, y luego usa la lerp función del Vector3.

El lerp() función del Scalar objeto toma tres parámetros:

  • Un número para la escala de origen

  • Un número para la escala objetivo

  • La cantidad, un valor de 0 a 1 que representa qué fracción del escalado realizar.

Para implementar este lerp en tu escena, recomendamos crear un componente personalizado para almacenar la información necesaria. También necesitas definir un sistema que implemente el escalado gradual en cada frame.



Moverse a velocidades irregulares entre dos puntos vía system

Mientras usas el método lerp, puedes hacer que la velocidad de movimiento sea no lineal. En el ejemplo anterior incrementamos la cantidad de lerp por una cantidad dada en cada frame, pero también podríamos usar una función matemática para aumentar el número exponencialmente u otras medidas que te den un ritmo de movimiento diferente.

También podrías usar una función que dé resultados recurrentes, como una función seno, para describir un movimiento que va y viene.

A menudo estas transiciones no lineales pueden dar mucha vida a una escena. Un movimiento que se acelera siguiendo una curva o que se desacelera gradualmente puede decir mucho sobre la naturaleza de un objeto o personaje. Incluso podrías aprovechar funciones matemáticas que añadan efectos de rebote.

El ejemplo anterior es igual al ejemplo de lerp lineal que hemos mostrado antes, pero el fraction campo mapeado a un valor no lineal en cada tick. Este valor no lineal se usa para calcular la lerp function, resultando en un movimiento que sigue una curva exponencial.

También puedes mapear una transición en rotación o en escala de la misma manera que se muestra arriba, mapeando una transición lineal a una curva.



Seguir un camino vía system

Puedes hacer que una entidad recorra un array de vectores, realizando un movimiento lerp entre cada uno para seguir un camino más complejo.

El ejemplo anterior define un camino 3D compuesto por cuatro vectores 3D. El PathTransportData custom component holds the same data used by the custom component in the lerp example above, but adds a path array, with all of the points in our path, and a pathTargetIndex campo para llevar la cuenta de qué segmento del camino se está usando actualmente.

El system es muy similar al system en el lerp example, but when a lerp action is completed, it sets the target y origin campos a nuevos valores. Si llegamos al final del camino, volvemos al primer valor del camino.



Tween de texturas

Para hacer que una textura se deslice suavemente, usa el Tween componente con la setTextureMove .

El tween de textura toma la siguiente información:

  • entity: La entidad cuya textura se moverá

  • start: Un Vector2 para la posición inicial

  • end: Un Vector2 para la posición final

  • duration: Cuántos milisegundos toma moverse entre las dos posiciones

Este otro parámetro opcional también está disponible:

  • movementType: (opcional), define si el movimiento será sobre el campo offset o el campo tiling. Por defecto usa offset.

  • easingFunction: Qué función de easing usar. Ver Non-linear tweens. Nota: Este parámetro solo se usa si se proporciona una duración.

Movimiento constante de textura

Para hacer que una textura se deslice constantemente, usa el Tween componente con la setTextureMoveContinuous .

El tween continuo de textura toma la siguiente información:

  • entity: La entidad cuya textura se moverá

  • direction: Un Vector2 para el movimiento

  • Cambia la velocidad a la que se reproduce una animación cambiando la propiedad: Cuántas unidades por segundo se moverá la entidad

Este otro parámetro opcional también está disponible:

  • movementType: define si el movimiento será sobre el campo offset o el campo tiling. Por defecto usa offset.

  • duration: Cuántos milisegundos sostener el movimiento. Después de este tiempo, el movimiento se detendrá.

Lee más sobre los tween de textura en el Texture Tweensarrow-up-right sección.

Última actualización