Mover Entities
Como mover, rodar e dimensionar uma entity gradualmente ao longo do tempo, com alterações incrementais.
Para mover, rodar ou redimensionar uma entidade na sua cena ao longo de um período de tempo, use o Tween componente. O engine realiza a transformação desejada de forma suave, atualizando a cada frame até que a duração especificada termine. Também os Transform valores do componente da entidade afetada são atualizados em tempo real caso seja necessário fazer verificações de proximidade no código da cena.
💡 Dica: No Scene Editor in Creator Hub, você pode mover entidades de forma no-code via Actions, veja Make any item smart.
O componente Tween possui as seguintes funções:
setMove: Mover entre dois pontossetRotate: Rodar entre duas direçõessetScale: Escalar entre dois tamanhossetMoveRotateScale: Transicionar simultaneamente em todos os três parâmetrossetMoveContinuous: Mover constantemente na mesma direçãosetRotateContinuous: Rodar constantemente na mesma direçãosetTextureMove: Deslocar a textura de um material entre duas posiçõessetTextureMoveContinuous: Deslocar a textura de um material constantemente na mesma direção
Mover entre dois pontos
Para mover uma entidade entre dois pontos, crie um Tween componente com a setMove função.
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
)A tween de movimento recebe as seguintes informações:
entity: A entidade a moverstart: Um Vector3 para a posição inicialend: Um Vector3 para a posição finalduration: Quantos milissegundos leva para mover entre as duas posições
Estes outros parâmetros opcionais também estão disponíveis:
faceDirection: Se true, a entidade é rotacionada para olhar na direção do movimento.easingFunction: Qual função de easing usar. Veja Non-linear tweens
Rodar entre duas direções
Para rodar uma entidade entre duas posições, crie um Tween componente com a setRotate função.
A tween de rotação recebe as seguintes informações:
start: Um Quaternion para a rotação inicialend: Um Quaternion para a rotação finalduration: Quantos milissegundos leva para mover entre as duas posições
Este outro parâmetro opcional também está disponível:
easingFunction: Qual função de easing usar. Veja Non-linear tweens
Rodar com um ponto de pivô
Ao rodar uma entidade, a rotação é sempre em referência à coordenada central da entidade. Para rodar uma entidade usando outro conjunto de coordenadas como ponto de pivô, crie uma segunda entidade (invisível) com o ponto de pivô como sua posição e torne-a pai da entidade que você deseja rotacionar.
Ao rodar a entidade pai, seus filhos serão todos rotacionados usando a posição do pai como ponto de pivô. Note que a position da entidade filha está em referência à da entidade pai.
Note que neste exemplo, o sistema está rotacionando a pivotEntity entidade, que é pai da childEntity entidade.
Escalar entre dois tamanhos
Para alterar a escala de uma entidade entre dois tamanhos, crie um Tween componente com seu modo definido como Tween.Mode.Scale.
A tween de escala recebe as seguintes informações:
start: Um Vector3 para o tamanho inicialend: Um Vector3 para o tamanho finalduration: Quantos milissegundos leva para mover entre as duas posições
Este outro parâmetro opcional também está disponível:
easingFunction: Qual função de easing usar. Veja Non-linear tweens
Non-linear tweens
Tweens podem seguir diferentes Easing Functions que afetam a taxa de mudança ao longo do tempo. Uma linear função significa que a velocidade da mudança é constante do início ao fim. Existem muitas opções para escolher, que desenham curvas de formas diferentes dependendo se o começo e/ou o fim iniciam devagar, e o quanto. Uma easeinexpo curva começa devagar e termina rápida, aumentando a velocidade exponencialmente, ao contrário de uma easeoutexpo curva que começa rápida e termina devagar.
💡 Dica: Experimente diferentes curvas de movimento. As diferenças são muitas vezes sutis, mas nós subconscientemente interpretamos informações de como as coisas se movem, como peso, atrito ou até personalidade.
O parâmetro opcional easingFunction toma seu valor do EasingFunction enum, que oferece as seguintes opções:
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
Rotação constante
Para fazer uma entidade girar constantemente, use o Tween componente com a setRotateContinuous função.
A tween de rotação contínua recebe as seguintes informações:
entity: A entidade a rotacionardirection: Um Quaternion para a rotaçãospeed: Quantos graus por segundo a entidade irá girar
Este outro parâmetro opcional também está disponível:
duration: Quantos milissegundos sustentar a rotação. Após esse tempo, a rotação irá parar.
Movimento constante
Para fazer uma entidade mover-se constantemente na mesma direção, use o Tween componente com a setMoveContinuous função.
A tween de movimento contínuo recebe as seguintes informações:
entity: A entidade a moverdirection: Um Vector3 para o movimentospeed: Quantos metros por segundo a entidade irá mover-se
Este outro parâmetro opcional também está disponível:
duration: Quantos milissegundos sustentar o movimento. Após esse tempo, o movimento irá parar.
A tween de movimento contínuo recebe as seguintes informações:
Sequências de Tween
Para fazer uma entidade executar uma série de tweens em sequência, use o TweenSequence componente. Este componente requer dois campos:
sequence: Um array com múltiplas definições de tween, que serão realizadas sequencialmente. O array pode estar vazio, caso em que apenas toca o tween atual.loop(opcional): Se não fornecido, a sequência é tocada apenas uma vez. Se o campo estiver presente, o valor deve ser um valor doTweenLoopenum. Valores aceitos são:TL_RESTART: Quando a sequência terminar, ela reinicia. Se o estado final não corresponder ao estado inicial, a entidade salta instantaneamente de um para o outro.TL_YOYO: Quando a sequência terminar, ela volta para trás, executando todos os tweens em reverso até alcançar o início novamente. Então começa mais uma vez.
Mover para frente e para trás
Para fazer uma plataforma mover-se constantemente para frente e para trás entre duas posições, deixe o sequence array vazio, e defina loop para TweenLoop.TL_YOYO
A entidade moverá-se para frente e para trás entre o ponto inicial e o ponto final, com a mesma duração e a mesma função de easing em ambas as direções.
Seguir um caminho
Para fazer uma entidade seguir um caminho mais complexo com múltiplos pontos, forneça uma lista de definições de tween no sequence de um TweenSequence componente.
Note que ao definir um tween dentro de um TweenSequence, você precisa usar o formato mais verboso de Tween.Mode.Move, ou Tween.Mode.Rotate, ou Tween.Mode.Scale para definir o tween. Neste formato mais verboso, você precisa especificar:
duration: Quantos milissegundos leva para mover entre as duas posiçõeseasingFunction: Qual função de easing usar. Veja Non-linear tweens. Neste formato o valor é obrigatório.mode: O modo do tween, que pode serTween.Mode.Move,Tween.Mode.Rotate, ouTween.Mode.Scale.
E dentro do campo mode você precisa especificar:
start: O valor inicial do tweenend: O valor final do tween
Ao término do tween
Use tweenSystem.tweenCompleted para detectar quando um tween terminou. Isso pode ser útil para executar ações quando um tween terminar, por exemplo para abrir a porta de um elevador.
Tweens simultâneos
Para mover, rodar e escalar uma entidade entre um estado inicial e um estado final, crie uma Tween componente com a setMoveRotateScale função. Esta função também pode ser usada em qualquer combinação desses três parâmetros.
A tween de movimento recebe as seguintes informações:
entity: A entidade a moverparams: Um objeto com vários parâmetros opcionaisposition: Um objeto com umstarteendvalue, ambos comoVector3.rotation: Um objeto com umstarteendvalue, ambos comoQuaternion.scale: Um objeto com umstarteendvalue, ambos comoVector3.duration: Quantos milissegundos leva para transicionar entre os dois conjuntos de valoreseasingFunction: Qual função de easing usar. Veja Non-linear tweens
Uma entidade só pode ter um Tween componente, e cada componente tween só pode executar uma transformação de cada vez. Através do setMoveRotateScale tween type, você pode fazer uma entidade mover-se lateralmente e também rotacionar ao mesmo tempo, mas ambos os movimentos seguirão a mesma linha do tempo. Se você precisar que as transições sejam independentes entre si, como solução alternativa, você pode usar entidades com hierarquia de pai/filho. Por exemplo, você pode ter uma entidade pai invisível que se move lateralmente, com um filho visível que rotaciona.
No snippet a seguir, uma entidade pai rotaciona enquanto uma filha aumenta de escala.
Pausar um tween
Para pausar um tween, altere a propriedade playing para false. Para retomá-lo, altere de volta para true.
Para encerrar um tween que não precisa continuar, apague o Tween componente da entidade. Se a entidade também estava usando um TweenSequence componente, apague esse também.
Tweens baseados em um sistema
Ao invés de usar o componente Tween e deixar o engine tratar da transformação, você pode preferir fazer essa transição incrementalmente, frame a frame, via um system na sua cena. Movendo a entidade uma pequena quantidade cada vez que a função roda.
Por um lado, isso lhe dá mais controle para recalcular movimentos em cada frame. Por outro lado, o código fica mais complicado, e jogadores com máquinas menos performáticas podem experimentar o tween como travado, notando cada incremento.
Mover via system
A maneira mais fácil de mover uma entidade é modificar gradualmente o valor position armazenado no Transform componente.
Neste exemplo estamos movendo uma entidade 0.1 metros por tick do loop do jogo.
Vector3.Forward() retorna um vetor que aponta para frente e mede 1 metro de comprimento. Neste exemplo estamos então escalando este vetor para 1/10 de seu comprimento com Vector3.scale(). Se nossa cena tiver 30 frames por segundo, a entidade está movendo-se a 3 metros por segundo de velocidade.

Rodar via system
A maneira mais fácil de rodar uma entidade é alterar gradualmente os valores no componente Transform incrementalmente, e executar isso como parte da função de um system.
Note que para combinar a rotação atual com cada incremento, estamos usando Quaternion.multiply. Em matemática de quaternions, você combina duas rotações multiplicando-as, NÃO somando-as. A rotação resultante de multiplicar um quaternion por outro será a rotação final equivalente após primeiro executar uma rotação e depois a outra.
Neste exemplo, estamos rotacionando a entidade em 1 grau na direção para cima em cada tick do loop do jogo.
💡 Dica: Para fazer uma entidade sempre rotacionar para olhar o jogador, você pode adicionar um Billboard componente.

Rodar via system sobre um ponto de pivô
Ao rodar uma entidade, a rotação é sempre em referência à coordenada central da entidade. Para rodar uma entidade usando outro conjunto de coordenadas como ponto de pivô, crie uma segunda entidade (invisível) com o ponto de pivô como sua posição e torne-a pai da entidade que você deseja rotacionar.
Ao rodar a entidade pai, seus filhos serão todos rotacionados usando a posição do pai como ponto de pivô. Note que a position da entidade filha está em referência à da entidade pai.
Note que neste exemplo, o sistema está rotacionando a pivotEntity entidade, que é pai da childEntity entidade.

Ajustar movimento para tempo de atraso
Suponha que o jogador visitando sua cena esteja lutando para acompanhar o ritmo da taxa de frames. Isso poderia resultar no movimento parecendo irregular, pois nem todos os frames são cronometrados igualmente mas cada um move a entidade pela mesma quantidade.
Você pode compensar esse tempo desigual usando o dt parâmetro para ajustar a escala do movimento.
O exemplo acima mantém o movimento aproximadamente na mesma velocidade que o exemplo de movimento acima, mesmo se a taxa de frames cair. Ao rodar a 30 frames por segundo, o valor de dt é 1/30.
Você também pode suavizar rotações da mesma forma multiplicando a quantidade de rotação por dt.
Mover entre dois pontos via system
Se você quiser que uma entidade se mova suavemente entre dois pontos, use o lerp (interpolação linear) algoritmo. Este algoritmo é muito conhecido no desenvolvimento de jogos, pois é realmente útil.
A lerp() função recebe três parâmetros:
O vetor para a posição de origem
O vetor para a posição alvo
A quantidade, um valor de 0 a 1 que representa que fração da translação fazer.
O algoritmo de interpolação linear encontra um ponto intermediário no caminho entre ambos os vetores que corresponde à quantidade fornecida.
Por exemplo, se o vetor de origem for (0, 0, 0) e o vetor alvo for (10, 0, 10):
Usando uma quantidade de 0 retornaria (0, 0, 0)
Usando uma quantidade de 0.3 retornaria (3, 0, 3)
Usando uma quantidade de 1 retornaria (10, 0, 10)
Para implementar isto lerp() na sua cena, recomendamos criar um componente customizado para armazenar a informação necessária. Você também precisa definir um system que implemente o movimento gradual em cada frame.

Rodar entre dois ângulos via system
Para rodar suavemente entre dois ângulos, use o slerp (esférica interpolação linear) algoritmo. Este algoritmo é muito similar a um lerp, mas ele lida com rotações em quaternion.
A slerp() função recebe três parâmetros:
A quaternion ângulo para a rotação de origem
A quaternion ângulo para a rotação alvo
A quantidade, um valor de 0 a 1 que representa que fração da translação fazer.
💡 Dica: Você pode passar valores de rotação em euler graus (de 0 a 360) usando Quaternion.fromEulerDegrees().
Para implementar isto na sua cena, recomendamos armazenar os dados que entram na função Slerp() em um componente customizadocomponente. Você também precisa definir um system que implemente a rotação gradual em cada frame.
📔 Nota: Você poderia representar a rotação com ângulos euler em vez disso como Vector3 valores e usar uma Lerp() função, mas isso implicaria uma conversão de Vector3 para Quaternion a cada frame. Valores de rotação são armazenados internamente como quaternions no Transform componente, então é mais eficiente para a cena trabalhar com quaternions.

Uma abordagem mais simples mas menos eficiente para isto aproveita a Quaternion.rotateTowards função, e evita usar quaisquer componentes personalizados.
No exemplo acima Quaternion.rotateTowards leva três argumentos: a rotação inicial, a rotação final desejada e o incremento máximo por quadro. Neste caso, como o incremento máximo é de dt * 10 graus, a rotação será realizada ao longo de um período de alguns 9 segundos.
Note que o sistema também verifica se a rotação está completa e, se estiver, remove o sistema do engine. Caso contrário, o sistema continuaria fazendo cálculos em cada quadro, mesmo depois que a rotação estivesse completa.
Alterar escala entre dois tamanhos via system
Se você quer que uma entidade mude de tamanho suavemente e sem alterar suas proporções, use o lerp (interpolação linear) algoritmo do Scalar objeto.
Caso contrário, se você quiser alterar os eixos em proporções diferentes, use Vector3 para representar a escala de origem e a escala alvo, e então use a lerp função do Vector3.
A lerp() função do Scalar objeto recebe três parâmetros:
Um número para a escala de origem
Um número para a escala alvo
A quantidade, um valor de 0 a 1 que representa qual fração da escala aplicar.
Para implementar este lerp na sua cena, recomendamos criar um componente personalizado para armazenar a informação necessária. Você também precisa definir um system que implemente o escalonamento gradual em cada quadro.

Mover em velocidades irregulares entre dois pontos via system
Ao usar o método lerp, você pode tornar a velocidade de movimento não linear. No exemplo anterior incrementamos a quantidade do lerp por um valor dado a cada quadro, mas também poderíamos usar uma função matemática para aumentar o número exponencialmente ou em outras medidas que deem um ritmo de movimento diferente.
Você também poderia usar uma função que dê resultados recorrentes, como uma função seno, para descrever um movimento que vai e volta.
Frequentemente essas transições não lineares podem trazer muita vida a uma cena. Um movimento que acelera seguindo uma curva ou que desacelera gradualmente pode dizer muito sobre a natureza de um objeto ou personagem. Você pode até aproveitar funções matemáticas que adicionam efeitos de quique.
O exemplo acima é igual ao exemplo linear de lerp que mostramos antes, mas o fraction campo mapeado para um valor não linear a cada tick. Esse valor não linear é usado para calcular a lerp função, resultando em um movimento que segue uma curva exponencial.
Você também pode mapear uma transição em rotação ou em escala da mesma forma que mostrado acima, mapeando uma transição linear para uma curva.

Seguir um caminho via system
Você pode fazer uma entidade percorrer um array de vetores, realizando um movimento lerp entre cada um para seguir um caminho mais complexo.
O exemplo acima define um caminho 3D composto por quatro vetores 3D. O PathTransportData componente personalizado contém os mesmos dados usados pelo componente personalizado no lerp exemplo acima, mas adiciona um path array, com todos os pontos do nosso caminho, e um pathTargetIndex campo para acompanhar qual segmento do caminho está sendo usado atualmente.
O sistema é muito similar ao sistema no lerp exemplo, mas quando uma ação de lerp é concluída, ele define os target e origin campos para novos valores. Se alcançarmos o final do caminho, retornamos ao primeiro valor do caminho.

Texture tweens
Para fazer uma textura deslizar suavemente, use o Tween componente com a setTextureMove função.
O texture tween recebe as seguintes informações:
entity: A entidade cuja textura será movidastart: Um Vector2 para a posição inicialend: Um Vector2 para a posição finalduration: Quantos milissegundos leva para mover entre as duas posições
Este outro parâmetro opcional também está disponível:
movementType: (opcional), define se o movimento será no campo offset ou no campo tiling. Por padrão usa offset.easingFunction: Qual função de easing usar. Veja Non-linear tweens. Nota: Este parâmetro é usado apenas se uma duração for fornecida.
Movimento constante de textura
Para fazer uma textura deslizar constantemente, use o Tween componente com a setTextureMoveContinuous função.
O texture continuous tween recebe as seguintes informações:
entity: A entidade cuja textura será movidadirection: Um Vector2 para o movimentospeed: Quantas unidades por segundo a entidade irá mover
Este outro parâmetro opcional também está disponível:
movementType: define se o movimento será no campo offset ou no campo tiling. Por padrão usa offset.duration: Quantos milissegundos sustentar o movimento. Após esse tempo, o movimento irá parar.
Leia mais sobre texture tweens em Texture Tweens seção.
Atualizado