For the complete documentation index, see llms.txt. This page is also available as Markdown.

Mover Entities

Como mover, rotacionar e escalar uma entity gradualmente ao longo do tempo, com alterações incrementais.

Para mover, rodar ou redimensionar uma entity na tua scene ao longo de um período de tempo, usa o Tween component. O engine executa a transformação desejada de forma suave, mostrando atualizações em cada frame até terminar a duração especificada. Além disso, os valores do Transform component da entity afetada são atualizados em tempo real, caso seja necessário fazer verificações de proximidade no código da scene.

💡 Dica: No Scene Editor in Creator Hub, podes mover entities de forma no-code através de Ações, vê Torna qualquer item smart.

O component Tween tem as seguintes funções:

  • setMove: Move entre dois pontos

  • setRotate: Rodar entre duas direções

  • setScale: Redimensionar entre dois tamanhos

  • setMoveRotateScale: Faz a transição simultaneamente nos três parâmetros

  • setMoveContinuous: Move constantemente na mesma direção

  • setRotateContinuous: Rodar constantemente na mesma direção

  • setTextureMove: Desloca a textura de um Material entre duas posições

  • setTextureMoveContinuous: Desloca continuamente a textura de um Material na mesma direção

Move entre dois pontos

Para mover uma entity entre dois pontos, cria um Tween component com a 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
)

O tween de movimento recebe as seguintes informações:

  • entity: A entity a mover

  • start: Um Vector3 para a posição inicial

  • end: Um Vector3 para a posição final

  • duration: Quantos milissegundos demora a mover entre as duas posições

Este outro parâmetro opcional também está disponível:

Rodar entre duas direções

Para rodar uma entity entre dois pontos, cria um Tween component com a setRotate function.

O tween de rotação recebe as seguintes informações:

  • start: Um Quaternion para a rotação inicial

  • end: Um Quaternion para a rotação final

  • duration: Quantos milissegundos demora a mover entre as duas posições

Este outro parâmetro opcional também está disponível:

Rodar com um ponto de pivô

Ao rodar uma entity, a rotação é sempre feita em referência à coordenada central da entity. Para rodar uma entity usando outro conjunto de coordenadas como ponto de pivô, cria uma segunda entity (invisível) com o ponto de pivô como posição e torna-a parent da entity que queres rodar.

Ao rodar a entity pai, as suas children serão todas rodadas usando a posição do pai como ponto de pivô. Nota que a position da child entity faz referência à da parent entity.

Nota que, neste exemplo, o system está a rodar a pivotEntity entity, que é parent da childEntity entity.

Redimensionar entre dois tamanhos

Para alterar a escala de uma entity entre dois tamanhos, cria um Tween component com a setScale function.

O tween de scale recebe as seguintes informações:

  • start: Um Vector3 para o tamanho inicial

  • end: Um Vector3 para o tamanho final

  • duration: Quantos milissegundos demora a mover entre as duas posições

Este outro parâmetro opcional também está disponível:

Mover a partir da posição atual

Enquanto um tween está ativo, o engine atualiza os valores do Transform component da entity em tempo real. Isto significa que podes ler a posição atual da entity a partir do seu Transform component a qualquer momento, e usar esse valor como o start de um novo tween. A entity então move-se de onde quer que esteja atualmente até ao alvo, independentemente de como lá chegou.

Redirecionar durante o trajeto

Ao chamar setMove (ou qualquer uma das outras funções tween) numa entity que já tem um tween em execução, substitui o tween em execução pelo novo. Como o start é lido a partir da posição em tempo real da entity, isto redireciona a entity de forma suave a meio do trajeto: muda de direção a partir de onde quer que esteja nesse momento, sem quaisquer saltos.

O exemplo abaixo move uma entity para o pad em que o player clicar. Se o player clicar noutro pad enquanto a entity ainda estiver em trajeto, a entity muda de direção suavemente em direção ao novo alvo.

Para executar lógica quando a entity chega ao destino, vê Ao terminar o tween.

Tweens não lineares

Tweens podem seguir diferentes Easing Functions que afetam a taxa de alteração ao longo do tempo. Uma linear function significa que a velocidade da alteração é constante do início ao fim. Há muitas opções para escolher, que desenham curvas com formatos diferentes dependendo de se o início e/ou o fim começam devagar, e em que medida. Uma easeinexpo curve começa devagar e termina rápido, aumentando a velocidade exponencialmente; pelo contrário, uma easeoutexpo curve começa rápido e termina devagar.

💡 Dica: Experimenta diferentes curvas de movimento. As diferenças são muitas vezes subtis, mas interpretamos subconscientemente informação a partir de como as coisas se movem, como peso, fricção ou até personalidade.

O opcional easingFunction parâmetro obtém o seu valor a partir da EasingFunction enum, que oferece as seguintes opções:

  • 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

Rotação constante

Para fazer uma entity rodar constantemente, usa o Tween component com a setRotateContinuous function.

O tween de rotação contínua recebe as seguintes informações:

  • entity: A entity a rodar

  • direction: Um Quaternion que determina o eixo em torno do qual rodar. Apenas o eixo desta rotação importa, o tamanho do seu ângulo é ignorado. Por exemplo, Quaternion.fromEulerDegrees(0, -1, 0) e Quaternion.fromEulerDegrees(0, -90, 0) comportam-se da mesma forma, ambos rodando em torno do y eixo numa direção negativa.

  • speed: Quantos graus por segundo a entity irá rodar. Um valor negativo roda na direção oposta.

Este outro parâmetro opcional também está disponível:

  • duration: Quantos milissegundos manter a rotação. Após esse tempo, a rotação para.

Movimento constante

Para fazer uma entity mover-se constantemente na mesma direção, usa o Tween component com a setMoveContinuous function.

O tween de movimento contínuo recebe as seguintes informações:

  • entity: A entity a mover

  • direction: Um Vector3 para o movimento

  • speed: Quantos metros por segundo a entity irá mover-se

Este outro parâmetro opcional também está disponível:

  • duration: Quantos milissegundos manter o movimento. Após esse tempo, o movimento para.

O tween de movimento contínuo recebe as seguintes informações:

Seguir um alvo em movimento

setMoveContinuous também é a ferramenta certa quando o destino continua a mudar, por exemplo uma entity que segue o player. É tentador, em vez disso, criar um novo setMove tween em cada frame, apontado para a posição mais recente do player, mas isso produz um tremor visível.

A razão é que a posição que lês a partir do Transform component de uma entity com tween é a posição que o engine comunicou pela última vez à scene, por isso fica atrasada alguns frames em relação ao local onde a entity realmente está. Quando passas esse valor como o start de um novo tween, o engine aplica-o imediatamente, e a entity salta para trás para onde estava há alguns frames. Uma dessas correções é impercetível, mas repeti-la muitas vezes por segundo não é.

setMoveContinuous evita o problema por completo, porque lhe dás uma direção e uma velocidade em vez de um ponto inicial. O engine continua a usar a posição real da entity, por isso substituir o tween para mudar de direção nunca faz a entity saltar.

Sequências de Tween

Para fazer uma entity reproduzir uma série de tweens em sequência, usa o TweenSequence component. Este component requer dois campos:

  • sequence: Um array com várias definições de tween, que serão executadas sequencialmente. O array pode estar vazio, caso em que apenas reproduz o tween atual.

  • loop (opcional): Se não for fornecido, a sequência é reproduzida apenas uma vez. Se o campo estiver presente, o valor tem de ser um valor do TweenLoop enum. Os valores aceites são:

    • TL_RESTART: Quando a sequência termina, recomeça. Se o último estado não corresponder ao primeiro, a entity salta instantaneamente de um para o outro.

    • TL_YOYO: Quando a sequência termina, ela recua, fazendo todos os tweens ao contrário até voltar a atingir o início. Depois começa mais uma vez.

Mover para trás e para a frente

Para fazer uma platform mover-se constantemente para trás e para a frente entre duas posições, deixa o sequence array vazio, e define loop para TweenLoop.TL_YOYO

A entity mover-se-á para trás e para a frente entre o ponto inicial e o ponto final, com a mesma duration e a mesma easing function em ambas as direções.

Seguir um caminho

Para fazer uma entity seguir um caminho mais complexo com vários pontos, fornece uma lista de definições de tween no sequence de um TweenSequence component.

Nota que, ao definir um tween dentro de um TweenSequence, tens de usar o formato mais detalhado de Tween.Mode.Move, ou Tween.Mode.Rotate, ou Tween.Mode.Scale para definir o tween. Neste formato mais detalhado, tens de especificar:

  • duration: Quantos milissegundos demora a mover entre as duas posições

  • easingFunction: Que easing function usar. Vê Tweens não lineares. Neste formato, o valor é obrigatório.

  • mode: O modo do tween, que pode ser Tween.Mode.Move, Tween.Mode.Rotate, ou Tween.Mode.Scale.

E dentro do mode campo, tens de especificar:

  • start: O valor inicial do tween

  • end: O valor final do tween

Ao terminar o tween

Usa tweenSystem.tweenCompleted para detetar quando um tween terminou. Isto pode ser útil para executar ações quando um tween acaba, por exemplo para abrir a porta de um elevador.

Tweens simultâneos

Para mover, rodar e redimensionar uma entity entre um estado inicial e um estado final, cria um Tween component com a setMoveRotateScale function. Esta function também pode ser usada em qualquer combinação destes três parâmetros.

O tween de movimento recebe as seguintes informações:

  • entity: A entity a mover

  • params: Um objeto com os seguintes parâmetros

    • position: (opcional) Um objeto com um start e end valor, tanto como Vector3.

    • rotation: (opcional) Um objeto com um start e end valor, tanto como Quaternion.

    • scale: (opcional) Um objeto com um start e end valor, tanto como Vector3. Pelo menos um dos position, rotation ou scale tem de ser fornecido.

    • duration: (obrigatório) Quantos milissegundos demora a transição entre os dois conjuntos de valores

    • easingFunction: (opcional) Que easing function usar. Vê Tweens não lineares

Uma Entity só pode ter um Tween component, e cada componente tween só pode executar uma transformação por vez. Através do setMoveRotateScale tipo de tween, você pode fazer uma Entity mover-se lateralmente e também rotacionar ao mesmo tempo, mas esses dois movimentos seguirão a mesma timeline. Se você precisar que as transições sejam independentes entre si, como alternativa, você pode usar entities com parent. Por exemplo, você pode ter uma Entity parent invisível que se move lateralmente, com um child visível que rotaciona.

No snippet a seguir, uma Entity parent rotaciona enquanto um child aumenta de escala.

Pausar um tween

Para pausar um tween, altere a playing propriedade para false. Para retomá-lo, altere-a de volta para true.

Para encerrar um tween que não precise ser continuado, delete o Tween component da Entity. Se a entitiy também estivesse usando um TweenSequence component, delete-o também.

Tweens baseados em um System

Em vez de usar o componente Tween e deixar o engine lidar com a transformação, você pode preferir fazer essa transição de forma incremental, frame a frame, por meio de um System na sua scene. Ao mover a Entity uma pequena quantidade cada vez que a função é executada.

Por um lado, isso lhe dá mais controle para recalcular os movimentos a cada frame. Por outro lado, o código fica mais complicado, e jogadores com máquinas menos performáticas podem experimentar o tween como lento, percebendo cada incremento.

Mover via System

A maneira mais fácil de mover uma Entity é modificar gradualmente o position valor armazenado no Transform component.

Neste exemplo, estamos movendo uma Entity em 0,05 metros por tick do game loop.

Vector3.Forward() retorna um vetor que aponta para frente e mede 1 metro de comprimento. Neste exemplo, então reduzimos esse vetor para 1/20 do seu comprimento com Vector3.scale(). Se a nossa scene tiver 30 frames por segundo, a Entity está se movendo a uma velocidade de 1,5 metros por segundo.



Rotacionar via System

A maneira mais fácil de rotacionar uma Entity é alterar gradualmente os valores no componente Transform de forma incremental e executar isso como parte da função de um System.

Observe que, para combinar a rotação atual com cada incremento, estamos usando Quaternion.multiply. Na matemática de quaternions, você combina duas rotações multiplicando-as, e NÃO somando-as. A rotação resultante de multiplicar um quaternion por outro será a rotação final equivalente após primeiro realizar uma rotação e depois a outra.

Neste exemplo, estamos rotacionando a Entity em 1 grau na direção para cima em cada tick do game loop.

💡 Dica: Para fazer uma Entity girar sempre para encarar o jogador, você pode adicionar um Billboard component.



Rotacionar via System sobre um ponto pivô

Ao rodar uma entity, a rotação é sempre feita em referência à coordenada central da entity. Para rodar uma entity usando outro conjunto de coordenadas como ponto de pivô, cria uma segunda entity (invisível) com o ponto de pivô como posição e torna-a parent da entity que queres rodar.

Ao rodar a entity pai, as suas children serão todas rodadas usando a posição do pai como ponto de pivô. Nota que a position da child entity faz referência à da parent entity.

Nota que, neste exemplo, o system está a rodar a pivotEntity entity, que é parent da childEntity entity.



Ajustar o movimento ao tempo delta

Suponha que o jogador que visita sua scene esteja com dificuldade de acompanhar o ritmo da taxa de frames. Isso pode fazer com que o movimento pareça aos solavancos, já que nem todos os frames têm o mesmo tempo, mas cada um move a Entity pela mesma quantidade.

Você pode compensar esse tempo irregular usando o dt parâmetro para ajustar a escala do movimento.

O exemplo acima mantém o movimento aproximadamente na mesma velocidade do 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 Entity se mova suavemente entre dois pontos, use o lerp (interpolação linear) algoritmo. Esse 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 de destino

  • A quantidade, um valor de 0 a 1 que representa que fração da translação deve ser feita.

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 de destino for (10, 0, 10):

  • Usar uma quantidade de 0 retornaria (0, 0, 0)

  • Usar uma quantidade de 0,3 retornaria (3, 0, 3)

  • Usar uma quantidade de 1 retornaria (10, 0, 10)

Para implementar isso lerp() na sua scene, recomendamos criar um component customizado para armazenar as informações necessárias. Você também precisa definir um System que implemente o movimento gradual em cada frame.



Rotacionar entre dois ângulos via System

Para rotacionar suavemente entre dois ângulos, use o slerp (spherical linear interpolation) algorithm. Esse algoritmo é muito semelhante a um lerp, mas ele lida com rotações de 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 de destino

  • A quantidade, um valor de 0 a 1 que representa que fração da translação deve ser feita.

💡 Dica: Você pode passar valores de rotação em euler graus (de 0 a 360) usando Quaternion.fromEulerDegrees().

Para implementar isso na sua scene, recomendamos armazenar os dados que entram na Slerp() função em um component customizado. Você também precisa definir um System que implemente a rotação gradual em cada frame.



Uma abordagem mais simples, porém menos eficiente, para isso aproveita a Quaternion.rotateTowards função e evita usar quaisquer component customizados.

No exemplo acima Quaternion.rotateTowards recebe três argumentos: a rotação inicial, a rotação final desejada e o incremento máximo por frame. Nesse caso, como o incremento máximo é de dt * 10 graus, a rotação será realizada ao longo de um período de cerca de 9 segundos.

Observe que o System também verifica se a rotação está concluída e, se estiver, remove o System do engine. Caso contrário, o System continuaria fazendo cálculos em cada frame, mesmo depois de a rotação estar concluída.

Alterar a escala entre dois tamanhos via System

Se você quiser que uma Entity 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 de destino, e então use o 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 de destino

  • A quantidade, um valor de 0 a 1 que representa que fração da escala deve ser aplicada.

Para implementar este lerp na sua scene, recomendamos criar um component customizado para armazenar as informações necessárias. Você também precisa definir um System que implemente a escala gradual em cada frame.



Mover a velocidades irregulares entre dois pontos via System

Ao usar o método lerp, você pode fazer a velocidade do movimento ser não linear. No exemplo anterior, incrementamos a quantidade de lerp em um valor dado a cada frame, mas também poderíamos usar uma função matemática para aumentar o número exponencialmente ou por outras medidas que lhe deem um ritmo de movimento diferente.

Você também poderia usar uma função que gere resultados recorrentes, como uma função seno, para descrever um movimento que vai e volta.

Muitas vezes, essas transições não lineares podem dar muita vida a uma scene. Um movimento que acelera ao longo de uma curva ou desacelera gradualmente pode dizer muito sobre a natureza de um objeto ou personagem. Você poderia até aproveitar funções matemáticas que adicionam efeitos de quique.

O exemplo acima é exatamente como o exemplo linear de lerp que mostramos antes, mas o fraction campo fraction é 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 na rotação ou na escala da mesma forma mostrada acima, mapeando uma transição linear para uma curva.



Seguir um caminho via System

Você pode fazer com que uma Entity percorra em loop um array de vetores, realizando um movimento de lerp entre cada um para seguir um caminho mais complexo.

O exemplo acima define um caminho 3D composto por quatro vetores 3D. O component customizado contém os mesmos dados usados pelo component customizado no exemplo acima, mas adiciona um array path com todos os pontos do nosso caminho e um campo pathTargetIndex para acompanhar qual segmento do caminho está atualmente em uso. PathTransportData O System é muito semelhante ao System no exemplo acima, mas, quando uma ação de lerp é concluída, ele define os campos target lerp origin com novos valores. Se alcançarmos o fim do caminho, retornamos ao primeiro valor do caminho. array, com todos os pontos do nosso caminho, e um pathTargetIndex campo para acompanhar qual segmento do caminho está atualmente em uso.

O System é muito semelhante ao System 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 fim do caminho, retornamos ao primeiro valor do caminho.



Tweens de Texture

Para fazer uma Texture deslizar suavemente, use o Tween component com a setTextureMove function.

O tween de Texture recebe as seguintes informações:

  • entity: A Entity da qual a Texture será movida

  • start: Um Vector2 para a posição inicial

  • end: Um Vector2 para a posição final

  • duration: Quantos milissegundos demora a 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 tiling. Por padrão, usa offset.

  • easingFunction: Que easing function usar. Vê Tweens não lineares.

Movimento contínuo de Texture

Para fazer uma Texture deslizar continuamente, use o Tween component com a setTextureMoveContinuous function.

O tween contínuo de Texture recebe as seguintes informações:

  • entity: A Entity da qual a Texture será movida

  • direction: Um Vector2 para o movimento

  • speed: Quantas unidades por segundo a Entity se moverá

Este outro parâmetro opcional também está disponível:

  • movementType: define se o movimento será no campo offset ou tiling. Por padrão, usa offset.

  • duration: Quantos milissegundos manter o movimento. Após esse tempo, o movimento para.

Leia mais sobre tweens de Texture na Tweens de Texture seção.

Atualizado