Texture flipbook : comment animer des sprites dans Unity, Godot et VRChat
Créez votre propre texture flipbook
Une texture flipbook lit une planche de sprites image par image sur une seule surface. Apprenez à en créer une dans Unity, Godot et VRChat, et à lire une vraie planche de sprites en direct en 3D.
Une texture flipbook est une planche de sprites qu'un shader lit image par image sur une seule surface. Il n'y a ni rig ni timeline : la planche contient chaque image dans une grille fixe, et le matériau déplace une petite fenêtre sur cette grille à un rythme constant. 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 re-téléversé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 manières de 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 cadence d'images, réduit cet indice à une colonne et une ligne, puis remappe les UV de la surface dans cette cellule unique. Frame = floor(time * fps) mod frameCount, column = frame mod columns, row = floor(frame / columns). Une planche de 6 x 6 à 10 FPS parcourt 36 images en 3,6 secondes, entièrement sur le GPU, sans téléversement par image et sans changement de 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ées par lignes, et c'est la valeur à laquelle l'indice reboucle. La cadence d'images est la vitesse à laquelle l'indice avance. Tout le reste — filtrage, mode de répétition, marges UV — sert à empêcher l'échantillonneur de lire en dehors de la cellule courante.
Le calcul de l'indice est court et mérite d'être écrit en entier. 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). Le sens vertical est le point qui piège le plus de monde. La plupart des outils de création de planches placent la ligne 0 en haut de l'image, alors que l'origine des UV dans Unity et Godot est 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 lues à 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. En 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 du 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 est à 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 rentrez 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'avancement de l'indice. floor(time * fps) donne l'image courante. |
| Mode de répétition | Clamp. Repeat laisse l'échantillonneur lire au-delà du bord de la planche. |
| Mode de filtrage | Point, avec mipmaps désactivées, ou rentrez les UV 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 pendant qu'un shader Lit ou Unlit standard fait l'échantillonnage. La première convient mieux aux effets qui doivent rester synchronisés avec le temps de jeu ; la seconde convient mieux quand l'animation doit être pilotée par un état d'Animator et visible 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 fournit en sortie 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 qu'en échantillonnant _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 pilote 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é _ST de la texture comme piste — elle apparaît sous forme de Vector4 sur le matériau.
02
Réglez la cadence d'échantillonnage du clip sur la même valeur que votre FPS cible. Si la cadence d'échantillonnage est inférieure au FPS voulu, les keyframes se superposent sur le même échantillon et l'animation est plus lente 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. Une interpolation linéaire mélange deux cellules et vous voyez les deux images à la fois, comme un effet de ghosting.
05
Assurez-vous que la dernière keyframe ne reprend pas la valeur de la première, 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 au premier accès 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 sur 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 cadence 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 est 1 / frameCount, et l'offset vaut simplement frame / frameCount. Pour une animation de 8 images de 256 x 256 pixels, 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 si possible la surface animée sur un matériau déjà présent sur l'avatar — 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é, tous les clients voient la même image ; un indice d'image calculé à partir du temps du shader est évalué localement et peut se trouver à 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 d'une cellule ; sa largeur est égale au nombre d'images multiplié par la largeur d'une 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é. N'activez Alpha Is Transparency que si la bande porte réellement un canal 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 cadence d'images pour obtenir la durée voulue — 8 images à 8 FPS forment une boucle d'une seconde.
05
Choisissez la source de l'image. 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 gardez Transparent que pour les effets aux 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 téléversé 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 par paliers. N'animez pas frame avec une courbe d'easing 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 reprenant 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 des UV dans Godot est en bas à gauche, comme dans 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 par paliers. |
| 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 que dans Unity. |
| Phaser 3 | this.load.spritesheet | frameWidth et frameHeight ; Phaser découpe la planche de gauche à droite, de haut en bas. |
| Phaser 3 | this.anims.create | Images issues de anims.generateFrameNumbers, plus frameRate et repeat: -1 pour boucler. |
Lisez 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 est la même opération indice-vers-UV que celle 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, là où les débordements 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 d'une 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, assez pour itérer sans étape de build.
Mini World est la scène la plus légère pour tester une seule planche — 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, donc 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.
Convertir un GIF est la voie qui cache le plus de travail, car un GIF n'est pas une suite 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 image par image en centièmes de seconde. Un shader flipbook n'accepte qu'une seule cadence, donc un timing variable doit être aplati en images dupliquées avant l'export.
Découper une grille en bande est mécanique : gardez la ligne voulue, rognez la hauteur à une cellule et laissez la largeur au nombre d'images multiplié par la largeur de cellule. C'est le bon choix quand une planche en grille ne sert qu'à une seule animation, car cela supprime l'axe vertical et la couture qui l'accompagne. Générer à 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 des images exportées une par une.
01
Aplatissez chaque image du GIF avant l'export. Décodez chaque image sur un canvas qui reprend l'image précédente, sinon vous exportez les rectangles de différence au lieu de l'image complète.
02
Normalisez le timing. Choisissez le délai GIF le plus court ou la médiane, puis dupliquez les images là où la source marquait une pause plus longue, afin que la planche soit lue à un seul FPS constant.
03
Disposez les images de gauche à droite, 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, rognez la hauteur à une cellule et gardez la largeur au nombre d'images multiplié par la largeur de cellule. Supprimez la cellule vide en fin de bande 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 vous laisse pas désactiver les mipmaps. Sinon, rentrez la fenêtre UV d'un demi-texel sur les quatre côtés.
06
Pour générer au lieu de convertir, écrivez l'action, le nombre d'images et le sens d'orientation, et laissez Agent Sprite Forge renvoyer une planche à cellules fixes plutôt que 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 affiche un sprite animé sur un maillage d'avatar. Vous réglez Rows, Columns et une cadence d'images, et vous laissez l'indice d'image dépendre du temps du shader ou vous 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 lire un GIF directement en 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 cadence 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 fixe. Le shader ne voit jamais le GIF.
Pourquoi ma texture flipbook déborde-t-elle entre les images ? +
L'échantillonneur 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 un rendu aux contours nets, et rentrez la fenêtre UV d'un demi-texel de chaque côté. Les débordements s'aggravent avec la distance, car c'est là que la chaîne de mip commence à moyenner les cellules voisines.
Quelle cadence 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 cadence, donc si la source avait un timing variable, dupliquez des images pour l'aligner plutôt que de tenter 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 lit comme une séquence, et elle supprime un axe d'erreur de couture. Les grilles servent aux planches qui regroupent plusieurs animations dans une même texture, où le shader ou le moteur sélectionne une ligne pour l'attente, la course ou l'attaque. Si une planche en grille ne donne 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 un jeu, avec 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.