Mover entities

Cómo mover, rotar y escalar una entity gradualmente en el tiempo, con cambios incrementales.

Para mover, rotar o cambiar el tamaño de una entidad en tu escena durante un período de tiempo, usa el Tween componente. El engine realiza la transformación deseada de forma suave, mostrando actualizaciones en cada frame hasta que finaliza 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

💡 Tip: En el Scene Editor in Creator Hubarrow-up-right, puedes mover entidades de forma no‑code a través de Actions, ver Haz inteligente cualquier itemarrow-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 el setMove función.

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 tarda en moverse entre las dos posiciones

También están disponibles estos otros parámetros opcionales:

  • 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 el setRotate función.

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 tarda en 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 toma respecto 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, todos sus hijos se rotarán usando la posición del padre como punto de pivote. Ten en cuenta que el position de la entidad hija está en referencia al de la entidad padre.

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

Escalar entre dos tamaños

Para cambiar la escala de una entidad entre dos tamaños, crea un Tween componente con su modo establecido en 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 tarda en moverse entre las dos posiciones

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

Non-linear tweens

Los tweens pueden seguir diferentes Funciones de Easing que afectan la tasa de cambio a lo largo del tiempo. Una linear function, significa que la velocidad del cambio es constante desde el inicio hasta el fin. Hay muchas opciones para elegir, que dibujan curvas con diferentes formas dependiendo de si el inicio y/o el final comienzan lentos, y cuánto. Un easeinexpo curve comienza lenta y termina rápida, aumentando la velocidad exponencialmente; en cambio una easeoutexpo curve comienza rápida y termina lenta.

circle-info

💡 Tip: 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 el setRotateContinuous función.

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

  • entity: La entidad a rotar

  • dirección: Un Quaternion para la rotación

  • speed: 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. Tras ese 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 el setMoveContinuous función.

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

  • entity: La entidad a mover

  • dirección: Un Vector3 para el movimiento

  • speed: 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. Tras ese tiempo, el movimiento se detendrá.

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

Secuencias de tweens

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 tweens, que se ejecutarán de forma secuencial. 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, haciendo todos los tweens en reversa hasta que vuelve al inicio. Luego comienza de nuevo.

Moverse de un lado a otro

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

La entidad se moverá de un lado a otro 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 tweens en el sequence de un TweenSequence component.

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 tarda en moverse entre las dos posiciones

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

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

Y dentro del campo mode , necesitas 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 finaliza, por ejemplo para abrir la puerta de un 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, puedes usar entidades parentadas. Por ejemplo, puedes tener una entidad padre invisible que se mueva lateralmente, con un hijo visible que rote.

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

Pausar un tween

Para pausar un tween, cambia la propiedad playing a false. Para reanudarlo, cámbiala de nuevo a true.

Para terminar un tween que no necesita continuar, 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, mediante 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 mediante un system

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

En este ejemplo estamos moviendo una entidad 0.1 metros por tick del bucle del juego.

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



Rotar mediante un 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 la 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 bucle del juego.

circle-info

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



Rotar mediante un system sobre un punto de pivote

Al rotar una entidad, la rotación siempre se toma respecto 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, todos sus hijos se rotarán usando la posición del padre como punto de pivote. Ten en cuenta que el position de la entidad hija está en referencia al de la entidad padre.

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



Ajustar el movimiento al tiempo de retardo

Supongamos que el jugador que visita tu escena tiene problemas 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 espaciados uniformemente pero cada uno mueve la entidad la misma cantidad.

Puedes compensar esta temporización desigual usando el parámetro dt 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 cae. Al ejecutarse 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 mediante un system

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

El lerp() function 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 traslación realizar.

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

Por ejemplo, si el vector 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 componente personalizadoarrow-up-right para almacenar la información necesaria. También necesitas definir un system que implemente el movimiento gradual en cada frame.



Rotar entre dos ángulos mediante un system

Para rotar suavemente entre dos ángulos, usa el slerp (spherical interpolación lineal). Este algoritmo es muy similar a un lerp, pero maneja rotaciones con quaterniones.

El slerp() function toma tres parámetros:

circle-info

💡 Tip: 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 componente personalizadoarrow-up-right. También necesitas definir un system que implemente la rotación gradual en cada frame.

circle-exclamation


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

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 llevará a cabo durante un período de unos 9 segundos.

Ten en cuenta que el system también comprueba si la rotación está completa y, de ser así, elimina el system del engine. De lo contrario, el system seguiría realizando cálculos en cada frame, incluso una vez completada la rotación.

Cambiar escala entre dos tamaños mediante un system

Si quieres que una entidad cambie de tamaño de forma suave y sin alterar sus proporciones, usa el lerp (algoritmo de interpolación lineal) del Scalar objeto.

De lo contrario, si quieres cambiar los ejes en proporciones distintas, 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 system que implemente el escalado gradual en cada frame.



Mover a velocidades irregulares entre dos puntos mediante un system

Mientras usas el método lerp, puedes hacer que la velocidad de movimiento sea no lineal. En el ejemplo anterior incrementamos la cantidad lerp por un monto dado 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 distinto.

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 aportar 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 que el ejemplo de lerp lineal que hemos mostrado antes, pero el campo fraction mapeado a un valor no lineal en cada tick. Este valor no lineal se usa para calcular la lerp función, 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 mostró arriba, mapeando una transición lineal a una curva.



Seguir un camino mediante un 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 una ruta 3D que está compuesta por cuatro vectores 3D. El PathTransportData componente personalizado contiene los mismos datos usados por el componente personalizado en el lerp ejemplo anterior, pero añade un path array, con todos los puntos de nuestra ruta, y un pathTargetIndex campo para llevar el registro de qué segmento de la ruta se está usando actualmente.

El sistema es muy similar al sistema en el lerp ejemplo, pero cuando una acción lerp se completa, establece los objetivo y origin campos con nuevos valores. Si llegamos al final de la ruta, volvemos al primer valor de la ruta.



Tween de texturas

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

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 tarda en 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 desplace de forma constante, usa el Tween componente con el setTextureMoveContinuous función.

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

  • entity: La entidad cuya textura se moverá

  • dirección: Un Vector2 para el movimiento

  • speed: 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. Tras ese tiempo, el movimiento se detendrá.

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

Última actualización