Mover Entities
Cómo mover, rotar y escalar un entity gradualmente con el tiempo, con cambios incrementales.
Para mover, rotar o cambiar el tamaño de un entity en tu scene durante un período de tiempo, usa el Tween component. 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 valores del Transform component del entity afectado se actualizan en tiempo real en caso de que sea necesario hacer comprobaciones de proximidad en el código de la scene.
💡 Consejo: En el Scene Editor en Creator Hub, puedes mover entities de una forma no-code mediante Actions, ver Haz cualquier item smart.
El componente Tween tiene las siguientes funciones:
setMove: Mover entre dos puntossetRotate: Rotar entre dos direccionessetScale: Escalar entre dos tamañossetMoveRotateScale: Transicionar simultáneamente en los tres parámetrossetMoveContinuous: Mover constantemente en la misma direcciónsetRotateContinuous: Rotar constantemente en la misma direcciónsetTextureMove: Desplazar la texture de un material entre dos posicionessetTextureMoveContinuous: Desplazar la texture de un material constantemente en la misma dirección
Mover entre dos puntos
Para mover un entity entre dos puntos, crea un Tween component con el setMove function.
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 toma la siguiente información:
entity: El entity que se va a moverstart: Un Vector3 para la posición inicialend: Un Vector3 para la posición finalduration: Cuántos milisegundos tarda en moverse entre las dos posiciones
También están disponibles estos otros parámetros opcionales:
faceDirection: Si es true, el entity se rota para mirar en la dirección del movimiento.easingFunction: Qué función de easing usar. Ver Tweens no lineales
Rotar entre dos direcciones
Para rotar un entity entre dos puntos, crea un Tween component con el setRotate function.
El tween de rotación toma la siguiente información:
start: Un Quaternion para la rotación inicialend: Un Quaternion para la rotación finalduration: Cuántos milisegundos tarda en moverse entre las dos posiciones
También está disponible este otro parámetro opcional:
easingFunction: Qué función de easing usar. Ver Tweens no lineales
Rotar con un punto de pivote
Cuando rotas un entity, la rotación siempre se calcula con referencia a la coordenada central del entity. Para rotar un entity usando otro conjunto de coordenadas como punto de pivote, crea un segundo entity (invisible) con el punto de pivote como posición y haz que sea el padre del entity que quieres rotar.
Cuando se rota el entity padre, todos sus hijos se rotarán usando la posición del padre como punto de pivote. Ten en cuenta que la posición del entity hijo hace referencia a la del entity padre.
Ten en cuenta que en este ejemplo, el system está rotando el pivotEntity entity, que es un padre del childEntity entity.
Escalar entre dos tamaños
Para cambiar el scale de un entity entre dos tamaños, crea un Tween component con su mode establecido en Tween.Mode.Scale.
El tween de escala toma la siguiente información:
start: Un Vector3 para el tamaño inicialend: Un Vector3 para el tamaño finalduration: Cuántos milisegundos tarda en moverse entre las dos posiciones
También está disponible este otro parámetro opcional:
easingFunction: Qué función de easing usar. Ver Tweens no lineales
Tweens no lineales
Los tweens pueden seguir distintos Easing Functions que afectan la velocidad del cambio a lo largo del tiempo. Una curva linear function, significa que la velocidad del cambio es constante de principio a fin. Hay muchas opciones para elegir, que dibujan curvas de distintas formas según si el inicio y/o el final empiezan despacio, y cuánto. Un easeinexpo empieza despacio y termina rápido, aumentando la velocidad exponencialmente; por el contrario, una curva easeoutexpo empieza rápido y termina despacio.
💡 Consejo: Experimenta con diferentes curvas de movimiento. Las diferencias suelen ser sutiles, pero interpretamos de forma subconsciente la información que transmiten los movimientos, como el peso, la fricción o incluso la personalidad.
El parámetro opcional easingFunction toma su valor del EasingFunction enum, que ofrece las siguientes opciones:
EF_EASEBACKEF_EASEBOUNCEEF_EASECIRCEF_EASECUBICEF_EASEELASTICEF_EASEEXPOEF_EASEINBACKEF_EASEINBOUNCEEF_EASEINCIRCEF_EASEINCUBICEF_EASEINELASTICEF_EASEINEXPOEF_EASEINQUADEF_EASEINQUARTEF_EASEINQUINTEF_EASEINSINEEF_EASEOUTBACKEF_EASEOUTBOUNCEEF_EASEOUTCIRCEF_EASEOUTCUBICEF_EASEOUTELASTICEF_EASEOUTEXPOEF_EASEOUTQUADEF_EASEOUTQUARTEF_EASEOUTQUINTEF_EASEOUTSINEEF_EASEQUADEF_EASEQUARTEF_EASEQUINTEF_EASESINEEF_LINEAR
Rotación constante
Para hacer que un entity rote constantemente, usa el Tween component con el setRotateContinuous function.
El tween de rotación continua toma la siguiente información:
entity: El entity que se va a rotardirection: Un Quaternion para la rotaciónspeed: Cuántos grados por segundo rotará el entity
También está disponible este otro parámetro opcional:
duration: Cuántos milisegundos mantener la rotación. Después de este tiempo, la rotación se detendrá.
Movimiento constante
Para hacer que un entity se mueva constantemente en la misma dirección, usa el Tween component con el setMoveContinuous function.
El tween de movimiento continuo toma la siguiente información:
entity: El entity que se va a moverdirection: Un Vector3 para el movimientospeed: Cuántos metros por segundo se moverá el entity
También está disponible este otro parámetro opcional:
duration: Cuántos milisegundos mantener el movimiento. Después de este tiempo, el movimiento se detendrá.
El tween de movimiento continuo toma la siguiente información:
Secuencias de Tweens
Para hacer que un entity reproduzca una serie de tweens en secuencia, usa el TweenSequence component. Este component 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 delTweenLoopenum. Los valores aceptados son:TL_RESTART: Cuando termina la secuencia, se reinicia. Si el último estado no coincide con el primero, el entity salta instantáneamente de uno al otro.TL_YOYO: Cuando termina la secuencia, vuelve hacia atrás, haciendo todos los tweens en orden inverso hasta llegar de nuevo al inicio. Luego comienza una vez más.
Mover hacia adelante y hacia atrás
Para hacer que una plataforma se mueva constantemente hacia adelante y hacia atrás entre dos posiciones, deja el sequence array vacío, y establece loop a TweenLoop.TL_YOYO
El entity se moverá hacia adelante y hacia atrás entre el punto inicial y el punto final, con la misma duración y la misma función de easing en ambas direcciones.
Seguir una ruta
Para hacer que un entity siga una ruta más compleja con múltiples puntos, proporciona una lista de definiciones de tween en el sequence de un TweenSequence componente.
Ten en cuenta que al definir un tween dentro de un TweenSequence, necesitas usar el formato más detallado de Tween.Mode.Move, o Tween.Mode.Rotate, o Tween.Mode.Scale para definir el tween. En este formato más detallado, debes especificar:
duration: Cuántos milisegundos tarda en moverse entre las dos posicioneseasingFunction: Qué función de easing usar. Ver Tweens no lineales. En este formato, el valor es obligatorio.mode: El modo del tween, que puede serTween.Mode.Move,Tween.Mode.Rotate, oTween.Mode.Scale.
Y dentro del campo mode debes especificar:
start: El valor inicial del tweenend: El valor final del tween
Al finalizar el tween
Usa tweenSystem.tweenCompleted para detectar cuándo ha terminado un tween. Esto puede ser útil para realizar acciones cuando un tween termina, por ejemplo, para abrir la puerta de un ascensor.
Tweens simultáneos
Para mover, rotar y escalar un entity entre un estado inicial y uno final, crea una Tween component con el setMoveRotateScale function. Esta función también se puede usar con cualquier combinación de estos tres parámetros.
El tween de movimiento toma la siguiente información:
entity: El entity que se va a moverparams: Un objeto con varios parámetros opcionalesposición: Un objeto con unstartyendvalue, tanto comoVector3.rotación: Un objeto con unstartyendvalue, tanto comoQuaternion.escala: Un objeto con unstartyendvalue, tanto comoVector3.duration: Cuántos milisegundos tarda en transicionar entre los dos conjuntos de valoreseasingFunction: Qué función de easing usar. Ver Tweens no lineales
Un entity solo puede tener un Tween component, y cada component de tween solo puede realizar una transformación a la vez. A través del setMoveRotateScale tween type, puedes hacer que un entity se mueva lateralmente y también rote al mismo tiempo, pero ambos movimientos seguirán la misma línea de tiempo. Si necesitas que las transiciones sean independientes entre sí, como solución alternativa puedes usar entities con parent. Por ejemplo, puedes tener un entity padre invisible que se mueva lateralmente, con un hijo visible que rote.
En el siguiente fragmento, un entity padre rota mientras un hijo escala hacia arriba.
Pausar un tween
Para pausar un tween, cambia la playing propiedad a false. Para reanudarlo, vuelve a cambiarla a true.
Para terminar un tween que no necesita continuar, elimina el Tween component del entity. Si el entity también estaba usando un TweenSequence component, elimina ese también.
Tweens basados en un system
En lugar de usar el componente Tween y dejar que el engine se encargue de la transformación, quizá prefieras hacer esta transición de forma incremental, frame por frame, mediante un system en tu scene. Moviendo el entity una pequeña cantidad cada vez que se ejecuta la function.
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 con lag, notando cada incremento.
Mover mediante system
La forma más sencilla de mover un entity es modificar gradualmente el posición valor almacenado en el Transform componente.
En este ejemplo estamos moviendo un entity 0.1 metros por tick del game loop.
Vector3.Forward() devuelve un vector que apunta hacia delante y mide 1 metro de longitud. En este ejemplo, luego reducimos ese vector a 1/10 de su longitud con Vector3.scale(). Si nuestra scene tiene 30 frames por segundo, el entity se mueve a una velocidad de 3 metros por segundo.

Rotar mediante system
La forma más sencilla de rotar un entity es cambiar gradualmente los valores del component Transform de forma incremental, y ejecutar esto como parte de la function 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 quaternions, combinas dos rotaciones multiplicándolas, NO sumándolas. La rotación resultante de multiplicar un quaternion por otro será la rotación final equivalente después de realizar primero una rotación y luego la otra.
En este ejemplo, estamos rotando el entity 1 grado hacia arriba en cada tick del game loop.
💡 Consejo: Para hacer que un entity rote siempre para mirar al player, puedes agregar un Billboard component.

Rotar mediante system sobre un punto de pivote
Cuando rotas un entity, la rotación siempre se calcula con referencia a la coordenada central del entity. Para rotar un entity usando otro conjunto de coordenadas como punto de pivote, crea un segundo entity (invisible) con el punto de pivote como posición y haz que sea el padre del entity que quieres rotar.
Cuando se rota el entity padre, todos sus hijos se rotarán usando la posición del padre como punto de pivote. Ten en cuenta que la posición del entity hijo hace referencia a la del entity padre.
Ten en cuenta que en este ejemplo, el system está rotando el pivotEntity entity, que es un padre del childEntity entity.

Ajustar el movimiento al tiempo de retraso
Supongamos que el player que visita tu scene está teniendo dificultades para seguir el ritmo del frame rate. Eso podría hacer que el movimiento parezca irregular, ya que no todos los frames tienen la misma duración, pero cada uno mueve el entity la misma cantidad.
Puedes compensar este tiempo irregular 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 las rotaciones de la misma manera multiplicando la cantidad de rotación por dt.
Mover entre dos puntos mediante system
Si quieres que un entity se mueva suavemente entre dos puntos, usa el lerp (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 de destino
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 recorrido entre ambos vectores que coincide con la cantidad proporcionada.
Por ejemplo, si el vector de origen es (0, 0, 0) y el vector de destino 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 scene, recomendamos crear un componente personalizado 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 system
Para rotar suavemente entre dos ángulos, usa el slerp (esférica lineal). Este algoritmo es muy similar a un lerp, pero maneja rotaciones de quaternion.
El slerp() function toma tres parámetros:
El quaternion ángulo para la rotación de origen
El quaternion ángulo para la rotación de destino
La cantidad, un valor de 0 a 1 que representa qué fracción de la traslación realizar.
💡 Consejo: Puedes pasar valores de rotación en euler grados (de 0 a 360) usando Quaternion.fromEulerDegrees().
Para implementar esto en tu scene, recomendamos almacenar los datos que van a la Slerp() function en un componente personalizado. También necesitas definir un system que implemente la rotación gradual en cada frame.
📔 Nota: Podrías, en su lugar, representar la rotación con ángulos euler como Vector3 valores y usar una Lerp() function, pero eso implicaría una conversión desde Vector3 a Quaternion en cada frame. Los valores de rotación se almacenan internamente como quaternions en el Transform component, por lo que para la scene es más eficiente trabajar con quaternions.

Un enfoque más sencillo pero menos eficiente para esto aprovecha la Quaternion.rotateTowards function, y evita usar cualquier custom component.
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, como el incremento máximo es de dt * 10 grados, la rotación se realizará en un período de un par de 9 segundos.
Ten en cuenta que el system también comprueba si la rotación está completa y, si es así, elimina el system del engine. De lo contrario, el system seguiría haciendo cálculos en cada frame, incluso una vez completada la rotación.
Cambiar el scale entre dos tamaños mediante system
Si quieres que un entity cambie de tamaño de forma suave y sin cambiar sus proporciones, usa el lerp (interpolación lineal) del Scalar objeto.
De lo contrario, si quieres cambiar cada eje con distintas proporciones, usa Vector3 para representar el scale de origen y el scale de destino, y luego usa la lerp function del Vector3.
El lerp() function del Scalar object toma tres parámetros:
Un número para el scale de origen
Un número para el scale de destino
La cantidad, un valor de 0 a 1 que representa qué fracción del escalado realizar.
Para implementar este lerp en tu scene, recomendamos crear un custom component 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 sistema
Al usar el método lerp, puedes hacer que la velocidad del movimiento sea no lineal. En el ejemplo anterior incrementamos la cantidad de lerp en una cantidad dada en cada frame, pero también podríamos usar una función matemática para aumentar el número exponencialmente o de otras formas que te den un ritmo de movimiento diferente.
También podrías usar una función que produzca 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 acelera sobre una curva o 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 mostramos antes, pero el fraction campo se mapea a un valor no lineal en cada tick. Este valor no lineal se usa para calcular la lerp función, lo que da como resultado un movimiento que sigue una curva exponencial.
También puedes mapear una transición en rotación o en scale de la misma manera que se muestra arriba, mapeando una transición lineal a una curva.

Seguir una ruta mediante sistema
Puedes hacer que una entity recorra en bucle un array de vectors, realizando un movimiento lerp entre cada uno para seguir una ruta más compleja.
El ejemplo anterior define una ruta 3D que está compuesta por cuatro vectors 3D. El PathTransportData custom component contiene los mismos datos usados por el custom component 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 control de qué segmento de la ruta se está usando actualmente.
El system es muy similar al system en el lerp ejemplo, pero cuando se completa una acción lerp, establece los campos target y origin con nuevos valores. Si llegamos al final de la ruta, volvemos al primer valor de la ruta.

Tweens de textura
Para hacer que una texture se deslice suavemente, usa el Tween component con el setTextureMove function.
El tween de textura toma la siguiente información:
entity: La entity de la que mover la texturestart: Un Vector2 para la posición inicialend: Un Vector2 para la posición finalduration: Cuántos milisegundos tarda en moverse entre las dos posiciones
También está disponible este otro parámetro opcional:
movementType: (opcional), define si el movimiento será en el campo offset o tiling. Por defecto usa offset.easingFunction: Qué función de easing usar. Ver Tweens no lineales. Nota: Este parámetro solo se usa si se proporciona una duration.
Movimiento constante de textura
Para hacer que una texture se deslice constantemente, usa el Tween component con el setTextureMoveContinuous function.
El tween continuo de textura toma la siguiente información:
entity: La entity de la que mover la texturedirection: Un Vector2 para el movimientospeed: Cuántas unidades por segundo se moverá la entity
También está disponible este otro parámetro opcional:
movementType: define si el movimiento será en el campo offset o tiling. Por defecto usa offset.duration: Cuántos milisegundos mantener el movimiento. Después de este tiempo, el movimiento se detendrá.
Lee más sobre los tweens de textura en Tweens de textura .
Última actualización