Texture flipbook : comment animer des sprites dans Unity, Godot et VRChat


Créez votre propre texture flipbook
Une texture flipbook joue une planche de sprites image par image sur une seule surface. Apprenez à en créer une dans Unity, Godot et VRChat, et à faire défiler une vraie planche de sprites en direct en 3D.
Une texture flipbook est une planche de sprites qu'un shader joue image par image sur une seule surface. Il n'y a ni rig ni timeline : la planche contient toutes les images dans une grille fixe, et le matériau déplace une petite fenêtre sur cette grille à vitesse constante. Une planche de 8 x 8 contient 64 images ; à 12 images par seconde, elle boucle en environ 5,3 secondes. Le maillage ne change jamais, aucune texture n'est rechargée, et toute l'animation coûte une seule lecture de texture.
Cette page couvre les quatre nombres dont un shader flipbook a besoin et la façon dont l'indice d'image se projette sur les coordonnées UV, les deux méthodes pour piloter une texture flipbook dans Unity, la configuration d'un flipbook Poiyomi sur un avatar VRChat, l'équivalent dans Godot et Phaser, et la création de votre propre planche à partir d'un GIF ou d'une description écrite.
Réponse rapide
Une texture flipbook est une planche de sprites utilisée comme animation de shader, indexée par ligne et par colonne au fil du temps. La planche occupe un seul emplacement de texture ; chaque évaluation du shader calcule un indice d'image à partir du temps écoulé et d'une fréquence d'images, réduit cet indice à une colonne et une ligne, puis remappe les UV de la surface dans cette unique cellule. Image = floor(time * fps) mod frameCount, colonne = frame mod columns, ligne = floor(frame / columns). Une planche de 6 x 6 à 10 FPS parcourt 36 images en 3,6 secondes, entièrement sur le GPU, sans chargement par image et sans modification du draw call.
Comment fonctionne une texture flipbook
Quatre nombres définissent l'animation. Les colonnes et les lignes décrivent la disposition de la planche. Le nombre d'images vaut normalement colonnes multiplié par lignes, et c'est la valeur à laquelle l'indice reboucle. La fréquence d'images est la vitesse à laquelle l'indice avance. Tout le reste — filtrage, mode de répétition, marges UV — existe pour empêcher le sampler de lire en dehors de la cellule courante.
Le calcul de l'indice est court et mérite d'être écrit. Pour un temps écoulé t : frame = floor(t * fps) mod frameCount, column = frame mod columns, row = floor(frame / columns). La fenêtre UV est alors tiling = (1 / columns, 1 / rows) et offset = (column / columns, row / rows). La direction verticale est le point qui piège le plus de monde. La plupart des outils de création de planches écrivent la ligne 0 en haut de l'image, alors que les origines UV d'Unity et de Godot sont en bas à gauche. Sur une planche dont la première ligne est en haut dans Unity, offset.y devient 1 - (row + 1) / rows, sinon les lignes sont jouées à l'envers et la première image de l'animation est la dernière ligne de la planche.
Le filtrage détermine si le résultat est propre. Réglez le mode de répétition de la planche sur Clamp. Avec Repeat, un échantillon au bord droit de la texture lit le bord gauche, si bien qu'une colonne de pixels de l'image 0 apparaît dans la dernière image de chaque ligne. Désactivez les mipmaps pour le pixel art aux contours nets, car la chaîne de mip moyenne les cellules voisines et l'animation devient floue dès que la surface se trouve à quelques mètres. Si le moteur ou le shader cible impose les mipmaps, laissez une marge transparente d'un ou deux pixels autour de chaque cellule, ou réduisez la fenêtre UV d'un demi-texel sur les quatre côtés.
| Valeur | Ce qu'elle contrôle |
|---|---|
| Columns | Images côte à côte. Définit le tiling horizontal d'une cellule : 1 / columns. |
| Rows | Lignes de la planche. Définit le tiling vertical : 1 / rows. Utilisez 1 pour une bande. |
| Frame count | Nombre total d'images indexées, normalement columns x rows. L'indice reboucle ici. |
| FPS | Vitesse d'avance de l'indice. floor(time * fps) donne l'image courante. |
| Wrap mode | Clamp. Repeat laisse le sampler lire au-delà du bord de la planche. |
| Filter mode | Point, avec les mipmaps désactivées, ou des UV réduits d'un demi-texel par cellule. |
Texture flipbook dans Unity
Il existe deux approches, et elles échouent de manières différentes. La première est un shader qui gère lui-même l'indice de ligne et de colonne et s'anime seul. La seconde est la fenêtre Animation qui pose des keyframes sur le tiling et l'offset du matériau, tandis qu'un shader Lit ou Unlit classique effectue l'échantillonnage. La première convient mieux aux effets qui doivent rester synchronisés avec le temps de jeu ; la seconde convient mieux lorsqu'il faut piloter l'animation par un état d'Animator et la voir dans la timeline aux côtés du reste de la scène.
Dans les deux cas, configurez d'abord l'import de la planche de sprites : Wrap Mode Clamp, Mip Maps désactivées, Filter Mode Point, et aucune compression sur le pixel art. Ces trois réglages causent plus de bugs de flipbook que le calcul du shader.
Approche 1 : un shader avec un indice de ligne et de colonne
Dans Shader Graph, le nœud Flipbook prend Columns, Rows et un indice d'image piloté par le temps, et produit les UV remappés. Dans un shader écrit à la main, exposez _Columns, _Rows et _Fps comme propriétés et calculez la cellule dans l'étape vertex ou fragment. Si l'animation doit être synchronisée entre plusieurs objets, pilotez l'indice d'image depuis un float de script plutôt que d'échantillonner _Time.y indépendamment dans chaque matériau, afin que deux flipbooks sur le même objet ne puissent pas se désynchroniser.
Approche 2 : la fenêtre Animation pilotant le tiling et l'offset
Cette approche anime le vecteur _ST de la texture. Les shaders Standard et Unlit intégrés utilisent _MainTex_ST ; URP Lit et Unlit utilisent _BaseMap_ST. Le tiling reste fixe à (1, 1 / rows) et seul offset.y change. Les étapes ci-dessous s'appliquent à cette approche.
01
Sélectionnez le matériau et ouvrez la fenêtre Animation. Créez un clip, puis ajoutez la propriété vecteur _ST de la texture comme piste — elle apparaît sous forme de Vector4 sur le matériau.
02
Réglez la fréquence d'échantillonnage du clip sur la même valeur que votre FPS cible. Si la fréquence d'échantillonnage est inférieure au FPS souhaité, les keyframes se superposent sur le même échantillon et l'animation se joue plus lentement que prévu.
03
Posez une keyframe sur offset.y à chaque image : valeur = 1 - (row + 1) / rows pour une planche dont la première ligne est en haut, tiling = (1, 1 / rows).
04
Réglez l'interpolation de chaque keyframe sur Constant dans l'éditeur de courbes. Linear mélange deux cellules et vous voyez les deux images en même temps, sous forme de ghosting.
05
Assurez-vous que la dernière keyframe ne reprend pas la valeur de la première image, sinon l'animation se fige pendant une image à la jointure de la boucle.
06
Si plusieurs renderers partagent le matériau, animez un MaterialPropertyBlock par renderer plutôt que de lire renderer.material, qui clone le matériau la première fois qu'on y accède et laisse le clone vivant pendant toute la durée de vie de l'objet.
Flipbook Poiyomi pour VRChat
La section Flipbook du shader Poiyomi fait défiler une fenêtre UV sur une planche directement dans le matériau, si bien qu'un seul emplacement de matériau peut afficher un sprite animé sur un maillage d'avatar. Elle expose Rows, Columns et une fréquence d'images, plus un mode où vous pilotez vous-même l'indice d'image au lieu de le laisser dépendre du temps du shader.
Utilisez une bande d'une seule ligne plutôt qu'une grille. Une bande ne donne au shader qu'un seul axe à parcourir, ce qui supprime entièrement la couture verticale. Avec une grille, la fenêtre UV doit descendre d'une ligne à la fin de chaque ligne, et la moindre erreur de filtrage, de niveau de mip ou d'arrondi au demi-texel à cette frontière échantillonne la ligne voisine — visible sous la forme d'une fine bande d'une autre image pendant la lecture. Une bande simplifie aussi l'indice d'image en une simple multiplication : la largeur d'une image en UV vaut 1 / frameCount, et l'offset vaut simplement frame / frameCount. Pour une animation de 8 images de cellules 256 x 256, la bande fait 2048 x 256 et reste une puissance de deux.
L'alpha compte davantage sur un avatar que dans une scène plate. Si le sprite a des contours nets, utilisez Cutout ou Opaque. Les flipbooks en file Transparent n'écrivent pas la profondeur et, sur un avatar, ils se trient par rapport au corps et entre eux d'une manière qui change avec l'angle de caméra. Gardez la surface animée sur un matériau déjà présent sur l'avatar dans la mesure du possible — chaque emplacement de matériau supplémentaire compte dans le rang de performance de votre avatar. Si l'indice d'image est piloté par un état d'Animator avec un paramètre synchronisé, chaque client voit la même image ; un indice d'image calculé à partir du temps du shader est évalué localement et peut se situer à un point différent de la boucle selon le spectateur.
01
Exportez les images sous forme d'une seule bande horizontale. La hauteur de la bande est égale à la hauteur de cellule ; la largeur de la bande est égale au nombre d'images multiplié par la largeur de cellule. Ne laissez pas de cellule vide à la fin.
02
Importez la texture avec Wrap Mode Clamp, Mip Maps désactivées et sRGB activé. Activez Alpha Is Transparency uniquement si la bande contient réellement de l'alpha.
03
Créez un matériau Poiyomi, affectez-le au maillage animé et ouvrez la section Flipbook.
04
Réglez Rows sur 1 et Columns sur le nombre d'images. Réglez la fréquence d'images pour correspondre à la durée souhaitée — 8 images à 8 FPS donnent une boucle d'une seconde.
05
Choisissez la source des images. Le mode Manual expose un indice d'image que vous pilotez depuis un état d'Animator ; le mode piloté par le temps boucle tout seul.
06
Sous Rendering, choisissez Cutout ou Opaque pour les sprites aux contours nets. Ne laissez Transparent que pour les effets à bords doux, et attendez-vous à des bizarreries de tri de profondeur.
07
Vérifiez la boucle : la dernière image ne doit pas être un doublon de la première, sinon le sprite se fige pendant une image à chaque cycle.
08
Testez sur un avatar publié avec un miroir, de près et depuis l'autre bout de l'instance. C'est avec la distance qu'apparaissent les problèmes de mip et de filtrage.
Flipbook dans Godot et Phaser
Dans Godot 4, la voie 2D est AnimatedSprite2D avec une ressource SpriteFrames. Importez la planche, ouvrez SpriteFrames, réglez Hframes et Vframes sur le nombre de colonnes et de lignes, ajoutez les images de l'animation, puis réglez la vitesse de l'animation en images par seconde et laissez Loop activé. SpriteFrames stocke l'animation sous forme d'une liste d'indices d'images, si bien qu'une planche en grille comme une bande unique fonctionnent sans aucun calcul UV de votre côté.
Si vous n'avez besoin que d'une seule animation, un simple Sprite2D est plus léger : réglez Hframes et Vframes une fois, puis faites avancer la propriété entière frame depuis un AnimationPlayer avec une interpolation step. N'animez pas frame avec une courbe d'interpolation par défaut — la valeur est un indice entier et l'interpoler revient soit à la figer sur une seule valeur, soit à faire clignoter deux cellules.
Pour un flipbook sur une surface 3D dans Godot, un ShaderMaterial avec le même calcul de ligne et de colonne que la version Unity est le chemin le plus court : uv = UV * vec2(1.0 / cols, 1.0 / rows) + vec2(col / cols, row / rows), la ligne étant calculée à partir de l'indice d'image. L'origine UV de Godot est en bas à gauche, comme celle d'Unity, donc une planche dont la première ligne est en haut nécessite le même retournement vertical.
Dans Phaser 3, la planche est chargée une fois et découpée au chargement. frameWidth et frameHeight définissent la cellule, les images sont numérotées de gauche à droite et de haut en bas, et l'animation est identifiée par des numéros d'images plutôt que par des coordonnées — il n'y a aucun shader à écrire et aucun calcul de ligne et de colonne à rater.
| Moteur | Objet | Ce que vous réglez |
|---|---|---|
| Godot 4 | AnimatedSprite2D + SpriteFrames | Hframes et Vframes sur la disposition de la planche, puis la vitesse de l'animation en FPS avec Loop activé. |
| Godot 4 | Sprite2D | Hframes et Vframes une fois, puis la propriété entière frame avancée par un AnimationPlayer avec une interpolation step. |
| Godot 4 | ShaderMaterial sur un maillage 3D | Columns, rows et un indice d'image dans le shader, avec le même remappage UV et le même retournement vertical qu'Unity. |
| Phaser 3 | this.load.spritesheet | frameWidth et frameHeight ; Phaser découpe la planche de gauche à droite et de haut en bas. |
| Phaser 3 | this.anims.create | Images issues de anims.generateFrameNumbers, plus frameRate et repeat: -1 pour boucler. |
Faites défiler une planche de sprites en direct en 3D
La scène jouable de cette section est The Cyclops' Island, qui tourne dans le constructeur de jeux 3D Neta Studio. Le flipbook à l'écran résulte de la même opération indice-vers-UV décrite plus haut, évaluée dans un shader Three.js sur le GPU — la différence est qu'elle s'exécute sur un vrai maillage dans une vraie scène, avec une caméra que vous contrôlez et des lumières qui bougent.
Cela compte plus qu'il n'y paraît. Un flipbook dans une scène Unity plate est généralement observé de face, où les fuites de couture et le mélange des mips sont difficiles à voir. Faites le tour d'une surface animée avec la caméra sous un angle rasant et les problèmes apparaissent immédiatement : une bande de la cellule voisine au bord de l'image, le dernier niveau de mip qui moyenne deux images en un flou, ou un bord alpha qui se lit correctement de face et disparaît de côté. La version navigateur raccourcit la boucle entre la création d'une planche et son affichage sur une surface au point d'itérer sans étape de build.
Mini World est la scène la plus légère pour tester une planche unique — moins de maillages et un chargement plus court. Agent Sprite Forge génère les images si vous n'avez pas encore de planche, et les deux scènes utilisent le même pipeline flipbook : une planche qui rend bien dans Mini World se comporte de la même façon dans The Cyclops' Island.
Créez votre propre planche
Trois voies mènent à une planche utilisable : convertir un GIF existant, découper une grille en une seule bande, ou générer des images à partir d'une description écrite. Les trois aboutissent au même fichier — un PNG dont toutes les cellules ont la même taille, disposées de gauche à droite et de haut en bas, avec une largeur de planche qui est un multiple exact de la largeur de cellule.
La conversion d'un GIF est la voie qui cache le plus de travail, car un GIF n'est pas une séquence d'images complètes. Les images sont souvent des différences partielles par rapport à l'image précédente, et les délais sont stockés par image en centièmes de seconde. Un shader flipbook n'accepte qu'une seule fréquence d'images, il faut donc aplatir les timings variables en dupliquant des images avant l'export.
Découper une grille en bande est mécanique : conservez la ligne voulue, recadrez la hauteur sur une cellule et gardez la largeur au nombre d'images multiplié par la largeur de cellule. C'est le bon réflexe lorsqu'une planche en grille sert à une seule animation, car cela supprime l'axe vertical et la couture qui l'accompagne. La génération à partir d'une description est la troisième voie — Agent Sprite Forge prend une action et un nombre d'images et renvoie une planche à taille de cellule fixe, ce qui élimine le travail d'alignement manuel d'images exportées une par une.
01
Aplatissez chaque image du GIF avant l'export. Décodez chaque image sur un canvas qui reporte l'image précédente, sinon vous exporterez les rectangles de différence au lieu de l'image.
02
Normalisez le timing. Choisissez le délai GIF le plus court ou le délai médian, puis dupliquez les images là où la source marquait une pause plus longue, afin que la planche se lise à un FPS constant.
03
Disposez les images de gauche à droite et de haut en bas, toutes les cellules de taille identique. Faites en sorte que les dimensions de la planche soient un multiple exact de la taille de cellule — une planche large de 9,5 cellules échantillonnera éternellement les mauvais texels.
04
Pour découper en bande, recadrez la hauteur sur une cellule et gardez la largeur au nombre d'images multiplié par la largeur de cellule. Supprimez la cellule vide en fin de planche si la grille source en comportait une.
05
Ajoutez une marge transparente d'un ou deux pixels autour de chaque cellule si le moteur cible ne permet pas de désactiver les mipmaps. Sinon, réduisez la fenêtre UV d'un demi-texel sur les quatre côtés.
06
Pour générer plutôt que convertir, écrivez l'action, le nombre d'images et la direction d'orientation, et laissez Agent Sprite Forge renvoyer une planche à cellules fixes au lieu d'exporter les images une par une et de les aligner à la main.
07
Vérifiez en faisant avancer l'indice d'image une image à la fois dans le moteur. Si une cellule laisse apparaître un fragment de sa voisine sur le bord, c'est la disposition de la planche ou la marge UV qui est en cause, pas le shader.
Entrez dans le monde auquel elle appartient
Un sprite est un personnage qui n'a nulle part où se tenir. La dernière étape est celle que personne d'autre ne propose : prenez la planche que vous venez de créer et placez-la dans un monde où l'on peut se promener — une petite île, une planète, un coin de rue sous la pluie. Chaque monde de ce site a été créé à partir d'une seule description écrite et publié sous forme de page jouable.
FAQ
Qu'est-ce qu'un flipbook Poiyomi ? +
C'est la section Flipbook du shader Poiyomi, qui fait défiler une fenêtre UV sur une planche de sprites au niveau d'un matériau, afin qu'un seul emplacement de matériau puisse afficher un sprite animé sur un maillage d'avatar. Vous réglez Rows, Columns et une fréquence d'images, et vous laissez soit l'indice d'image dépendre du temps du shader, soit le pilotez depuis un état d'Animator. Une bande d'une seule ligne est préférable car elle supprime la couture verticale entre les lignes.
Peut-on utiliser un GIF directement comme flipbook ? +
Non. Un GIF stocke des délais par image et souvent uniquement les pixels qui ont changé, alors qu'un shader flipbook attend une seule texture et une fréquence d'images constante. Convertissez-le d'abord : aplatissez chaque image sur la précédente, normalisez le timing et écrivez le résultat dans une grille de cellules fixes. Le shader ne voit jamais le GIF.
Pourquoi ma texture flipbook bave-t-elle entre les images ? +
Le sampler lit en dehors de la fenêtre de la cellule courante. Réglez le mode de répétition de la texture sur Clamp, désactivez les mipmaps pour les visuels aux contours nets, et réduisez la fenêtre UV d'un demi-texel de chaque côté. Le phénomène s'aggrave avec la distance, car c'est là que la chaîne de mip commence à moyenner les cellules voisines.
Quelle fréquence d'images choisir pour un flipbook ? +
8 à 12 FPS donnent un rendu animé à la main, adapté aux sprites de personnages ; 24 à 30 conviennent au feu, à l'eau et aux autres effets continus. Le shader n'a qu'une seule fréquence, donc si la source avait un timing variable, dupliquez des images pour l'ajuster plutôt que d'essayer de faire varier la vitesse en cours de boucle.
Faut-il une grille, ou une seule ligne suffit-elle ? +
Une seule ligne suffit pour tout ce qui se joue comme une séquence, et elle supprime un axe d'erreur de couture. Les grilles servent aux planches qui regroupent plusieurs animations dans une seule texture, où le shader ou le moteur sélectionne une ligne pour l'inactivité, la course ou l'attaque. Si une grille ne produit qu'une seule animation, découpez-la en bande.
Un flipbook fonctionne-t-il avec le shader Lit d'Unity URP ? +
Pas tel quel — URP Lit n'a pas d'indice d'image. Utilisez Shader Graph avec le nœud Flipbook, qui prend Columns, Rows et un indice piloté par le temps, ou animez le tiling et l'offset de _BaseMap_ST du matériau avec une interpolation de keyframe constante. Les shaders Standard et Unlit intégrés utilisent _MainTex_ST selon les mêmes règles.
Retour au constructeur de jeux 3D
Les 31 mondes, jeux et scènes 3D terminés sont réunis sur une seule page — tous jouables.
Ouvrir la bibliothèque d'assets de sprites
Chaque asset de cette bibliothèque est un PNG transparent prêt pour le jeu, accompagné d'un prompt enregistré — Ressources de planches de sprites et Planches de sprites gratuites, classées par action, style et sujet. Consultation et téléchargement gratuits.