Flipbook Texture: Como animar sprites na Unity, Godot e VRChat
Crie sua própria flipbook texture
Uma flipbook texture reproduz um sprite sheet quadro a quadro em uma única superfície. Aprenda a criar uma na Unity, Godot e VRChat, e veja um sprite sheet real sendo animado ao vivo em 3D.
Uma flipbook texture é um sprite sheet que um shader reproduz quadro a quadro em uma única superfície. Não há rig nem timeline: a folha contém cada quadro em uma grade fixa, e o material move uma pequena janela por essa grade a uma taxa constante. Uma folha de 8 x 8 contém 64 quadros; a 12 quadros por segundo, o loop dura cerca de 5,3 segundos. A malha nunca muda, nenhuma textura é reenviada e toda a animação custa uma única consulta de textura.
Esta página aborda os quatro números de que um shader de flipbook precisa e como o índice de quadro é mapeado nas coordenadas UV, as duas formas de controlar uma flipbook texture na Unity, como um flipbook do Poiyomi é configurado em um avatar de VRChat, o equivalente no Godot e no Phaser, e como criar sua própria folha a partir de um GIF ou de uma descrição escrita.
Resposta rápida
Uma flipbook texture é um sprite sheet usado como animação de shader, indexado por linha e coluna ao longo do tempo. A folha fica em um único slot de textura; cada avaliação do shader calcula um índice de quadro a partir do tempo decorrido e de uma taxa de quadros, reduz esse índice a uma coluna e uma linha, e remapeia as UVs da superfície para essa única célula. Frame = floor(time * fps) mod frameCount, column = frame mod columns, row = floor(frame / columns). Uma folha de 6 x 6 a 10 FPS percorre 36 quadros em 3,6 segundos, inteiramente na GPU, sem envio por quadro e sem alteração de draw call.
Como funciona uma flipbook texture
Quatro números definem a animação. Columns e rows descrevem o layout da folha. Frame count normalmente é columns vezes rows, e é o valor no qual o índice dá a volta. Frame rate é a velocidade com que o índice avança. Todo o resto — filtragem, wrap mode, insets de UV — existe para impedir que o sampler leia fora da célula atual.
A matemática do índice é curta e vale a pena escrever. Dado o tempo decorrido t: frame = floor(t * fps) mod frameCount, column = frame mod columns, row = floor(frame / columns). A janela de UV é então tiling = (1 / columns, 1 / rows) e offset = (column / columns, row / rows). A direção vertical é a parte que costuma confundir. A maioria das ferramentas de criação de folhas escreve a linha 0 no topo da imagem, enquanto as origens de UV da Unity e do Godot ficam no canto inferior esquerdo. Em uma folha com a primeira linha no topo na Unity, offset.y passa a ser 1 - (row + 1) / rows, caso contrário as linhas tocam invertidas e o primeiro quadro da animação é a última linha da folha.
A filtragem decide se o resultado fica limpo. Defina o wrap mode da folha como Clamp. Com Repeat, uma amostra na borda direita da textura lê a borda esquerda, então uma coluna de pixels do quadro 0 aparece dentro do último quadro de cada linha. Desative os mipmaps para pixel art de bordas duras, porque a cadeia de mips faz a média das células vizinhas e a animação vira um borrão assim que a superfície fica a alguns metros de distância. Se a engine ou o shader de destino forçar mipmaps, deixe uma margem transparente de um ou dois pixels ao redor de cada célula, ou faça o inset da janela de UV em meio texel nos quatro lados.
| Valor | O que controla |
|---|---|
| Columns | Quadros lado a lado. Define o tiling horizontal de uma célula: 1 / columns. |
| Rows | Linhas na folha. Define o tiling vertical: 1 / rows. Use 1 para uma tira. |
| Frame count | Total de quadros indexados, normalmente columns x rows. O índice dá a volta aqui. |
| FPS | Velocidade com que o índice avança. floor(time * fps) fornece o quadro atual. |
| Wrap mode | Clamp. Repeat permite que o sampler leia além da borda da folha. |
| Filter mode | Point, com mipmaps desativados, ou inset das UVs em meio texel por célula. |
Flipbook texture na Unity
Existem dois caminhos, e eles falham de formas diferentes. O caminho um é um shader que controla o índice de linha e coluna e se anima sozinho. O caminho dois é a janela Animation criando keyframes no tiling e offset do material enquanto um shader Lit ou Unlit comum faz a amostragem. O caminho um é melhor para efeitos que precisam ficar sincronizados com o tempo do jogo; o caminho dois é melhor quando você precisa que a animação seja controlada por um estado do Animator e visível na timeline junto com todo o resto da cena.
De qualquer forma, configure primeiro a importação do sprite sheet: Wrap Mode Clamp, Mip Maps desativados, Filter Mode Point e sem compressão em pixel art. Essas três configurações causam mais bugs de flipbook do que a matemática do shader.
Caminho 1: um shader com índice de linha e coluna
No Shader Graph, o nó Flipbook recebe Columns, Rows e um índice de quadro controlado pelo tempo e produz as UVs remapeadas. Em um shader escrito à mão, exponha _Columns, _Rows e _Fps como propriedades e calcule a célula no estágio de vértice ou de fragmento. Se a animação precisar ficar sincronizada entre objetos, controle o índice de quadro a partir de um float de script em vez de amostrar _Time.y de forma independente em cada material, para que dois flipbooks no mesmo objeto não se dessincronizem.
Caminho 2: a janela Animation controlando tiling e offset
Este caminho anima o vetor _ST da textura. O Standard e o Unlit integrados usam _MainTex_ST; o Lit e o Unlit da URP usam _BaseMap_ST. O tiling permanece fixo em (1, 1 / rows) e apenas offset.y muda. As etapas abaixo se aplicam a este caminho.
01
Selecione o material e abra a janela Animation. Crie um clipe e adicione a propriedade de vetor _ST da textura como uma faixa — ela aparece como um Vector4 no material.
02
Defina a taxa de amostragem do clipe com o mesmo número do FPS desejado. Se a taxa de amostragem for menor que o FPS desejado, os keyframes se acumulam na mesma amostra e a animação toca mais devagar do que o pretendido.
03
Crie um keyframe em offset.y uma vez por quadro: valor = 1 - (row + 1) / rows para uma folha com a primeira linha no topo, tiling = (1, 1 / rows).
04
Defina a interpolação de cada keyframe como Constant no editor de curvas. Linear mistura duas células e você vê os dois quadros ao mesmo tempo como ghosting.
05
Certifique-se de que o último key não repita o valor do primeiro quadro, ou a animação fica parada por um quadro na emenda do loop.
06
Se vários renderers compartilham o material, anime um MaterialPropertyBlock por renderer em vez de ler renderer.material, que clona o material na primeira vez que você o acessa e deixa o clone vivo por todo o tempo de vida do objeto.
Flipbook do Poiyomi para VRChat
A seção Flipbook do shader Poiyomi desliza uma janela de UV por uma folha no próprio material, então um único slot de material pode mostrar um sprite animado em uma malha de avatar. Ela expõe Rows, Columns e uma taxa de quadros, além de um modo em que você controla o índice de quadro em vez de deixá-lo correr pelo tempo do shader.
Use uma tira de uma única linha em vez de uma grade. Uma tira dá ao shader um único eixo para percorrer, o que elimina totalmente a emenda vertical. Com uma grade, a janela de UV precisa descer uma linha ao fim de cada linha, e qualquer erro de filtragem, nível de mip ou arredondamento de meio texel nessa fronteira amostra a linha vizinha — visível como uma faixa fina de um quadro diferente durante a reprodução. Uma tira também transforma o índice de quadro em uma multiplicação direta: a largura do quadro em UV é 1 / frameCount, e o offset é apenas frame / frameCount. Para uma animação de 8 quadros de células de 256 x 256, a tira fica 2048 x 256 e permanece uma potência de dois.
O alfa importa mais em um avatar do que em uma cena plana. Se o sprite tem bordas duras, use Cutout ou Opaque. Flipbooks na fila Transparent não escrevem profundidade e, em um avatar, se ordenam em relação ao corpo e entre si de formas que mudam com o ângulo da câmera. Mantenha a superfície animada em um material que já esteja no avatar sempre que possível — cada slot de material extra conta contra o rank de desempenho do seu avatar. Se o índice de quadro for controlado por um estado do Animator com um parâmetro sincronizado, todos os clientes veem o mesmo quadro; um índice de quadro calculado a partir do tempo do shader é avaliado localmente e pode estar em um ponto diferente do loop para espectadores diferentes.
01
Exporte os quadros como uma única tira horizontal. A altura da tira é igual à altura da célula; a largura da tira é igual ao número de quadros vezes a largura da célula. Não deixe uma célula sobrando no fim.
02
Importe a textura com Wrap Mode Clamp, Mip Maps desativados e sRGB ativado. Ative Alpha Is Transparency apenas se a tira realmente tiver alfa.
03
Crie um material Poiyomi, atribua-o à malha animada e abra a seção Flipbook.
04
Defina Rows como 1 e Columns como o número de quadros. Defina a taxa de quadros para corresponder à duração desejada — 8 quadros a 8 FPS é um loop de um segundo.
05
Escolha a origem dos quadros. O modo Manual expõe um índice de quadro que você controla a partir de um estado do Animator; o modo controlado pelo tempo faz o loop sozinho.
06
Em Rendering, defina Cutout ou Opaque para sprites de bordas duras. Deixe Transparent apenas para efeitos de bordas suaves, e espere peculiaridades de ordenação de profundidade.
07
Verifique o loop: o último quadro não pode ser uma duplicata do primeiro, ou o sprite congela por um quadro a cada ciclo.
08
Teste em um avatar enviado com um espelho, de perto e do outro lado da instância. A distância é onde aparecem os problemas de mip e filtragem.
Flipbook no Godot e no Phaser
No Godot 4, o caminho 2D é o AnimatedSprite2D com um recurso SpriteFrames. Importe a folha, abra SpriteFrames, defina Hframes e Vframes com o número de colunas e linhas, adicione os quadros da animação e então defina a velocidade da animação em quadros por segundo e deixe Loop ativado. O SpriteFrames armazena a animação como uma lista de índices de quadro, então tanto uma folha em grade quanto uma tira única funcionam sem nenhuma matemática de UV da sua parte.
Se você só precisa de uma animação, um Sprite2D comum é mais leve: defina Hframes e Vframes uma vez e depois avance a propriedade inteira frame a partir de um AnimationPlayer com interpolação step. Não faça tween de frame com uma curva de easing padrão — o valor é um índice inteiro e interpolá-lo ou resulta em um único valor arredondado para baixo ou pisca entre duas células.
Para um flipbook em uma superfície 3D no Godot, um ShaderMaterial com a mesma matemática de linha e coluna da versão da Unity é o caminho mais curto: uv = UV * vec2(1.0 / cols, 1.0 / rows) + vec2(col / cols, row / rows), com a linha calculada a partir do índice de quadro. A origem de UV do Godot é o canto inferior esquerdo, assim como na Unity, então uma folha com a primeira linha no topo precisa do mesmo flip vertical.
No Phaser 3, a folha é carregada uma vez e fatiada no momento do carregamento. frameWidth e frameHeight definem a célula, os frames são numerados da esquerda para a direita e de cima para baixo, e a animação é identificada por números de quadro em vez de coordenadas — não há shader para escrever nem aritmética de linha e coluna para errar.
| Engine | Objeto | O que você define |
|---|---|---|
| Godot 4 | AnimatedSprite2D + SpriteFrames | Hframes e Vframes com o layout da folha, depois a velocidade da animação em FPS com Loop ativado. |
| Godot 4 | Sprite2D | Hframes e Vframes uma vez, depois a propriedade inteira frame avançada por um AnimationPlayer com interpolação step. |
| Godot 4 | ShaderMaterial em uma malha 3D | Columns, rows e um índice de quadro no shader, com o mesmo remapeamento de UV e flip vertical da Unity. |
| Phaser 3 | this.load.spritesheet | frameWidth e frameHeight; o Phaser fatia a folha da esquerda para a direita, de cima para baixo. |
| Phaser 3 | this.anims.create | Frames de anims.generateFrameNumbers, mais frameRate e repeat: -1 para fazer o loop. |
Anime um sprite sheet ao vivo em 3D
A cena jogável desta seção é The Cyclops' Island, rodando no construtor de jogos 3D da Neta Studio. O flipbook na tela é a mesma operação de índice para UV descrita acima, avaliada em um shader Three.js na GPU — a diferença é que ele está rodando em uma malha real, em uma cena real, com uma câmera que você controla e luzes que se movem.
Isso importa mais do que parece. Um flipbook em uma cena plana da Unity geralmente é visto de frente, onde o vazamento de emenda e a mistura de mips são difíceis de perceber. Gire a câmera ao redor de uma superfície animada em um ângulo rasante e os problemas aparecem imediatamente: uma faixa da célula vizinha na borda do quadro, o último nível de mip fazendo a média de dois quadros em um borrão, ou uma borda alfa que fica correta de frente e desaparece de lado. A versão no navegador encurta o ciclo entre criar uma folha e vê-la em uma superfície o suficiente para iterar sem uma etapa de build.
Mini World é a cena menor para testar uma única folha — menos malhas e carregamento mais curto. O Agent Sprite Forge gera os quadros se você ainda não tem uma folha, e as duas cenas usam o mesmo caminho de flipbook, então uma folha que fica correta no Mini World se comporta da mesma forma em The Cyclops' Island.
Crie sua própria folha
Existem três caminhos para chegar a uma folha utilizável: converter um GIF existente, cortar uma grade para uma única tira, ou gerar quadros a partir de uma descrição escrita. Os três terminam no mesmo arquivo — um PNG com todas as células do mesmo tamanho, dispostas da esquerda para a direita e de cima para baixo, com a largura da folha sendo um múltiplo exato da largura da célula.
Converter um GIF é o caminho com mais trabalho oculto, porque um GIF não é uma sequência de quadros completos. Os quadros frequentemente são diffs parciais em relação ao quadro anterior, e os delays são armazenados por quadro em centésimos de segundo. Um shader de flipbook aceita uma única taxa de quadros, então o timing variável precisa ser achatado em quadros duplicados antes da exportação.
Cortar uma grade para uma tira é mecânico: mantenha a linha necessária, corte a altura para uma célula e deixe a largura como o número de quadros vezes a largura da célula. É a escolha certa quando uma folha em grade é usada como uma única animação, porque remove o eixo vertical e a emenda que vem com ele. Gerar a partir de uma descrição é o terceiro caminho — o Agent Sprite Forge recebe uma ação e um número de quadros e retorna uma folha com tamanho de célula fixo, o que elimina o trabalho de alinhar manualmente quadros exportados um a um.
01
Achate cada quadro do GIF antes de exportar. Decodifique cada quadro sobre um canvas que carrega o quadro anterior adiante, ou você exportará os retângulos de diff em vez da imagem.
02
Normalize o timing. Escolha o delay mais curto ou a mediana do GIF e depois duplique quadros onde a origem se mantinha por mais tempo, para que a folha toque em um FPS constante.
03
Disponha os quadros da esquerda para a direita, de cima para baixo, com todas as células idênticas em tamanho. Faça as dimensões da folha um múltiplo exato do tamanho da célula — uma folha com 9,5 células de largura amostrará os texels errados para sempre.
04
Para cortar em uma tira, corte a altura para uma célula e mantenha a largura no número de quadros vezes a largura da célula. Exclua a célula vazia no fim se a grade de origem tiver uma.
05
Adicione uma margem transparente de um ou dois pixels ao redor de cada célula se a engine de destino não permitir desativar os mipmaps. Caso contrário, faça o inset da janela de UV em meio texel nos quatro lados.
06
Para gerar em vez de converter, escreva a ação, o número de quadros e a direção frontal, e deixe o Agent Sprite Forge retornar uma folha de células fixas em vez de exportar quadros um a um e alinhá-los à mão.
07
Verifique avançando o índice de quadro um por vez na engine. Se qualquer célula mostrar um pedaço da vizinha na borda, o layout da folha ou o inset de UV está errado, não o shader.
Entre no mundo ao qual ela pertence
Um sprite é um personagem sem lugar para ficar. O último passo é o que ninguém mais oferece: pegue a folha que você acabou de criar e coloque-a em um mundo pelo qual alguém possa caminhar — uma pequena ilha, um planeta, uma esquina chuvosa. Todos os mundos deste site foram criados a partir de uma única descrição escrita e publicados como uma página que você pode jogar.
FAQ
O que é um flipbook do Poiyomi? +
É a seção Flipbook do shader Poiyomi, que desliza uma janela de UV por um sprite sheet em um material para que um único slot de material possa mostrar um sprite animado em uma malha de avatar. Você define Rows, Columns e uma taxa de quadros, e deixa o índice de quadro correr pelo tempo do shader ou o controla a partir de um estado do Animator. Prefere-se uma tira de uma única linha porque ela elimina a emenda vertical entre as linhas.
É possível fazer flipbook de um GIF diretamente? +
Não. Um GIF armazena delays por quadro e muitas vezes apenas os pixels que mudaram, enquanto um shader de flipbook espera uma única textura e uma taxa de quadros constante. Converta-o primeiro: achate cada quadro sobre o anterior, normalize o timing e escreva o resultado em uma grade de células fixas. O shader nunca vê o GIF.
Por que minha flipbook texture vaza entre os quadros? +
O sampler está lendo fora da janela da célula atual. Defina o wrap mode da textura como Clamp, desative os mipmaps para arte de bordas duras e faça o inset da janela de UV em meio texel de cada lado. O vazamento piora com a distância, porque é aí que a cadeia de mips começa a fazer a média das células vizinhas.
Que taxa de quadros uma flipbook deve usar? +
8 a 12 FPS parece animado à mão e combina com sprites de personagem; 24 a 30 combina com fogo, água e outros efeitos contínuos. O shader tem exatamente uma taxa, então se a origem tinha timing variável, duplique quadros para igualar em vez de tentar variar a velocidade no meio do loop.
Preciso de uma grade, ou uma linha basta? +
Uma linha basta para qualquer coisa que toque como uma sequência, e elimina um eixo de erro de emenda. Grades servem para folhas que empacotam várias animações em uma única textura, onde o shader ou a engine seleciona uma linha para idle, corrida ou ataque. Se apenas uma animação sai de uma folha em grade, corte-a em uma tira.
Um flipbook funciona com o shader Lit da URP da Unity? +
Não de imediato — o Lit da URP não tem índice de quadro. Use o Shader Graph com o nó Flipbook, que recebe Columns, Rows e um índice controlado pelo tempo, ou anime o tiling e o offset de _BaseMap_ST do material com interpolação de keyframe constante. O Standard e o Unlit integrados usam _MainTex_ST sob as mesmas regras.
Voltar ao Construtor de Jogos 3D
Todos os 31 mundos, jogos e cenas 3D finalizados estão em uma única página — todos eles jogáveis.
Abrir a biblioteca de assets de sprite
Todos os assets desta biblioteca são PNG transparentes e prontos para jogos, com um prompt registrado — Recursos de sprite sheet e Sprite sheets gratuitos, marcados por ação, estilo e assunto. Grátis para explorar e baixar.