Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Animated GIFS

Discussion in 'Scripting' started by Velketor, Apr 14, 2008.

  1. Velketor

    Velketor

    Joined:
    Sep 15, 2007
    Posts:
    110
    Does Unity support Animated GIFS?

    If yes, is there anything special I need to do in order for the animated GIFS to actually function properly on game objects or GUI textures?

    I'd like to use them as textures on objects such as water, lava, etc =)

    Any information is greatly appreciated! Thank you!

    --Velk
     
    JorgeAmVF and BMRG14 like this.
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Nope, but you can save the individual frames as separate textures, and cycle through an array of those textures. In some cases (if you don't need tiling, for example), you can save all the frames into one texture and animate the texture offset. I think there's a script on the wiki for that.

    --Eric
     
    BMRG14 likes this.
  3. Velketor

    Velketor

    Joined:
    Sep 15, 2007
    Posts:
    110
    Thanks Eric5h5,

    Thanks for the information...do you know how I can tell Unity to cycle through a series of textures (specifically, animated GIFS?) I'd like to use Animated GIFS as textures in my game.

    So far, I've tried attaching the following script to my gameobject with the Animated GIF as it's material/texture:

    Code (csharp):
    1.  
    2. // this line of code will make the Movie Texture begin playing
    3. renderer.material.mainTexture.Play();
    4.  
    Any ideas? I'm still learning how to script -- so any information is greatly appreciated. Thank you!
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    As I said, you can't use animated GIFs, but you can save the individual frames as separate textures, and cycle through an array of those textures:

    Code (csharp):
    1. var frames : Texture[];
    2. var framesPerSecond = 10;
    3.  
    4. function Update() {
    5.     var index : int = (Time.time * framesPerSecond) % frames.Length;
    6.     renderer.material.mainTexture = frames[index];
    7. }
    --Eric
     
  5. Velketor

    Velketor

    Joined:
    Sep 15, 2007
    Posts:
    110
    Thank you so much for the amazing script Eric5h5!

    It works really well and solved my question(s) =)

    Now that I've experimented with some of the possibilities of animated GIFS in Unity...I was wondering if it would also be possible to import a movie (.mov, .mpeg, etc) and have Unity simply play the movie at 10 frames per second.

    It is much easier for me to set what frames play per second compared to manually importing each image and linking them all to the textures within the script you provided me -- thanks again for the script .

    Does that make sense?

    Any information is helpful =) Thanks!

    --Velk :D
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes; see "MovieTexture" in the docs for that. However, that only works with Pro. Also, it's intended for actual movies rather than animated textures like water, etc.--there's overhead for decompressing movies on the fly that you wouldn't want with continuously animated textures, not to mention that you can't use alpha channels in movies. I know having separate frames isn't the most convenient thing ever, but it's unlikely you have too many frames for animated textures due to memory concerns.

    --Eric
     
  7. Velketor

    Velketor

    Joined:
    Sep 15, 2007
    Posts:
    110
    Thanks for the information/quick response =)

    I'll stick with the script you posted -- however, I have been trying to figure out a way to have a variable on the script that I can adjust from the Inspector.

    This would allow me the ability set a specific frame that I'd like the "Animated GIF" to stop on.

    Here is what I've tried so far:
    Code (csharp):
    1.  
    2. WrapMode.ClampForever
    What should I add to the script shown BELOW in order for it to allow my GIF animation to stop on a desired frame, preferably a variable I can tweak from the Inspector...

    Code (csharp):
    1.  
    2. var frames : Texture[];
    3. var framesPerSecond = 10;
    4.  
    5. function Update() {
    6.    var index : int = (Time.time * framesPerSecond) % frames.Length;
    7.    renderer.material.mainTexture = frames[index];
    8. }
    9.  
    10.  
    Once again, thank you for your help -- any additional information is always appreciated =)

    --Velk
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's for animations on 3D objects. To stop on a desired frame, you could make a variable that's exposed to the inspector, and in the Update function, compare that to the "index" variable, and only have the rest of the code run if "index" is less than or equal to that value.

    --Eric
     
    ezizka likes this.
  9. Velketor

    Velketor

    Joined:
    Sep 15, 2007
    Posts:
    110
    There has to be a way to stop the script from cycling through the image sequence repeatedly. I've tried all kinds of additional code...nothing seems to stop the infamous GIF sequence from playing in Unity.

    Any ideas? I'm an Arts guy more than a programmer so a line of code or a website link where I can find the information and research it would be much appreciated =) Thanks again!

    --Velk
     
  10. groovfruit

    groovfruit

    Joined:
    Apr 26, 2010
    Posts:
    257

    But this doesn't work for GUITextures as the poster originally requested. How does one animate GUITextures (no meshes)
     
  11. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Instead of using renderer.material.mainTexture, you can assign the GUITexture's texture property. Otherwise, the code is the same.
     
    twobob likes this.
  12. Ailos

    Ailos

    Joined:
    Sep 14, 2011
    Posts:
    13
    This is C#
    Start () ....
    public Texture2D []frames;

    OnGUI ()..... (instead of Update)
    int index = (int) (Time.time * framesPerSecond) % frames.Length;
     
  13. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Why are you resurrecting a thread from over a year ago with code that is horribly incorrect?
     
  14. Misung

    Misung

    Joined:
    Nov 23, 2012
    Posts:
    1
  15. RKSandswept

    RKSandswept

    Joined:
    Apr 26, 2013
    Posts:
    22
    Using ZNE GIF as a Menu Background
    SOLVED: Turns out my GIF is 1024 x 768 x 1 byte x 300 frames.
    But ZNE expands it to 1024x768x4x300 thus 943 MB. Oops.
    Changed the type to a GIF Movie and now memory use is fine.
    (Not set to Load All Frames at first)

    ---------------------------------------

    I got ZNE GIF and it crashes. I share a GUITexture, and a single Zne Gif Animation (Script)so I call update in each of my menu objects. Sitting in a menu doing nothing else uses up memory vey fast. 3.5 GB ram in about 10 seconds:!:

    I narrowed it down to the line
    Code (csharp):
    1.  z.Update_Frame();
    Notes:
    (Also tried GifComponent_Update() and it has the same problem)
    (The gif is 3.6 MB on disk, a full screen background)
    (If I set to Load all frames at first, it burns up 2.3 GB of memory, then is stable)
    (Loading in a image viewer only takes 31 MB for the whole viewer and image)
    (My app is about 800MB after start up, in menus, not in-game yet, if I delete the ZNE Gif component.)
    (Starting ZNE GIF alone takes about 1.7 GB, even if Zne Gif Animation is disabled, and the gif file removed)
    Any ideas why?

    Called from Update in all menu components: (Except the one menu that 'owns' the zneGifAnimation)
    Code (csharp):
    1.  
    2.      public void _updateMenuBackgroundAnimation()
    3.     {
    4.         Note: (This has been changed to be zneGifMovie instead)
    5.         zneGifAnimation z = MainMenu.thisInstance.GetComponent<zneGifAnimation>();
    6.         if(z != null)
    7.         {
    8.             z.Update_Frame();
    9.         }
    10.     }
    11.  
    Then to draw it as a menu background:
    Code (csharp):
    1.  
    2.     public void fillMenuBackground()
    3.     {
    4.         Texture t = mainMenuBackground;
    5.         if(MainMenu.thisInstance.guiTexture != null)
    6.         {
    7.             t = MainMenu.thisInstance.guiTexture.texture;
    8.         }
    9.         GUI.DrawTexture( new Rect(0,0,Screen.width, Screen.height), t, ScaleMode.StretchToFill);
    10.     }
    11.  
     
    Last edited: Jul 27, 2013
  16. Venryx

    Venryx

    Joined:
    Sep 25, 2012
    Posts:
    444
    Last edited: Mar 3, 2014
    KDevS likes this.
  17. Zervot

    Zervot

    Joined:
    Jul 6, 2014
    Posts:
    1
    or just think outside the box, and use tools unity provides in fun ways. I like to avoid any heavy scripting. I was working on replicating the Deadspace style of GUI for doors, ect. First i made my GUI images for the layers and made them 75% occ in gimp, and made the rest Trans on alpha. In Unity I just put them on very thin cubes. Layering the ultra thin cubes(with image textures, set to trans/Diffuse). then here is the lol part, just make animations in the animator and let them loop forever of them spinning. Of course a little java to make them spin, appear on collision, ect would be very easy as well. In the end the player sees your animated "texture" the way u want them to see. also works great for cheat gui, attach the planes to the camera, bam poor mans gui. Always find a way to cheat the system.
     
  18. rame16

    rame16

    Joined:
    Nov 21, 2012
    Posts:
    29
    Hi there! The wiki tuto you mentioned worked fine, but how is that to put the gif on a model?
     
  19. fidel1029

    fidel1029

    Joined:
    May 22, 2016
    Posts:
    1
    You can try converting the gif to an mp4 or other video format and then set that as a VideoTexture. It would still need a script to play, but it would be significantly simpler. Here is the VideoTexture tutorial:
    http://docs.unity3d.com/Manual/class-MovieTexture.html
    As for gif to mp4 tools, there are plenty online converters out there.
     
  20. Aestial

    Aestial

    Joined:
    Jan 22, 2013
    Posts:
    1
    Hi everybody,
    I've found a really nice solution called UniGif. You can find the repository here:
    https://github.com/WestHillApps/UniGif
    Tested on Android, iOS, MacOS, Windows and Editor. May need some changes if load from StreamingAssets (Android).

    Cheers,
    Jaime
     
  21. prasanthdot87

    prasanthdot87

    Joined:
    Feb 22, 2017
    Posts:
    1
    I had struggled a fair bit trying to get this done. So, putting it out there in case it helps someone.
    Requirement was to retrieve spritesheet stored as ByteStream from a SQLite file and cycle through each of these sprites to make it look like a gif.
    To achieve this, I retrieve data from SQLite at the start of the scene and store it in a static class.
    I also create an empty sprite with default scale and rotation to be visible in your camera. Then create a new script under this sprite. Script is below.

    You can change the location of code from OnEnable to anything that suits your need.
    Code (CSharp):
    1. public class imageController : MonoBehaviour
    2.     {
    3.         private int counter;
    4.  
    5.         private int rows;
    6.         private int cols;
    7.         private Sprite rawImage;
    8.      
    9.         public GameObject mainActor;
    10.  
    11.         private Sprite[] individualImages;
    12.  
    13.  
    14.         private void OnDisable()
    15.         {
    16.             this.individualImages = null;
    17.             base.CancelInvoke();
    18.         }
    19.  
    20.         private void OnEnable()
    21.         {
    22.             this.individualImages = null;
    23.             base.CancelInvoke();
    24.             this.counter = 0;
    25.             byte[] data = DBBean.bytMedia[DBBean.currentRecord];
    26.             this.rows = DBBean.intRows[DBBean.currentRecord];
    27.             this.cols = DBBean.intCols[DBBean.currentRecord];
    28.             Texture2D texture2D = new Texture2D(1, 1);
    29.             texture2D.LoadImage(data);
    30.             this.rawImage = Sprite.Create(texture2D, new Rect(0f, 0f, (float)texture2D.width, (float)texture2D.height), new Vector2(0.2f, 0.2f));
    31.             float height = this.rawImage.rect.height;
    32.             float width = this.rawImage.rect.width;
    33.             float num = width / (float)this.cols;
    34.             float num2 = height / (float)this.rows;
    35.             int num3 = 0;
    36.             this.individualImages = new Sprite[this.rows * this.cols];
    37.             for (int i = 0; i < this.rows; i++)
    38.             {
    39.                 for (int j = this.cols - 1; j > -1; j--)
    40.                 {
    41.                     Color[] pixels = texture2D.GetPixels((int)num * j, (int)num2 * i, (int)num, (int)num2);
    42.                     Texture2D texture2D2 = new Texture2D((int)num, (int)num2);
    43.                     texture2D2.SetPixels(0, 0, (int)num, (int)num2, pixels);
    44.                     texture2D2.Apply();
    45.                     this.individualImages[num3] = Sprite.Create(texture2D2, new Rect(0f, 0f, (float)texture2D2.width, (float)texture2D2.height), new Vector2(0.2f, 0.2f));
    46.                     num3++;
    47.                 }
    48.             }
    49.             base.InvokeRepeating("RenderSprites", 0.001f, DBBean.flAnimationInterval[DBBean.currentRecord]);
    50.             this.counter = this.individualImages.Length - 1;
    51.         }
    52.  
    53.         private void RenderSprites()
    54.         {
    55.             if (this.counter < 0)
    56.             {
    57.                 this.counter = this.individualImages.Length - 1;
    58.             }
    59.             this.mainActor.GetComponent<SpriteRenderer>().sprite = this.individualImages[this.counter];
    60.             this.mainActor.transform.localScale = new Vector3(DBBean.flScalex[DBBean.currentRecord], DBBean.flScaley[DBBean.currentRecord], DBBean.flScalez[DBBean.currentRecord]);
    61.             this.mainActor.transform.position = new Vector3(DBBean.flCoordinatex[DBBean.currentRecord], DBBean.flCoordinatey[DBBean.currentRecord], DBBean.flCoordinatez[DBBean.currentRecord]);
    62.             this.mainActor.transform.eulerAngles = new Vector3(DBBean.flRotatex[DBBean.currentRecord], DBBean.flRotatey[DBBean.currentRecord], DBBean.flRotatez[DBBean.currentRecord]);
    63.  
    64.             this.counter--;
    65.         }
    66.  
    67.     }
    Edit : I realised that the above code freezes the camera when sprites are created from the spritesheet(>150 images, 255X425pixels). I could improve the performance by converting the stuff in OnEnable to a Coroutine & invoking it from OnEnable, also made OnEnable to run InvokeRepeating. Since Texture.Load and Sprite.Create takes up too much time, I used 'yield return null' to pause coroutine execution momentarily, to reduce the screen freeze.
     
    Last edited: May 30, 2017
  22. megarg

    megarg

    Joined:
    Sep 17, 2017
    Posts:
    5
    Try this method:

    1. Go to https://ezgif.com/split to split your animated gif into frames.

    2. Download the zip file and extract all the images to a folder in your project.

    3. Copy/Paste the code below in a C# script called ExplosionController(or whatever you want)

    • NOTE: If you down't call the script ExplosionController, make sure to change the "ExplosionController" line in the code to whatever your filename is.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class ExplosionController : MonoBehaviour {
    6.     public Sprite[] frames;
    7.     public Image explosion;
    8.     public float frameRate = 0.1f;
    9.  
    10.     private int currentImage;
    11.     // Use this for initialization
    12.     void Start () {
    13.         currentImage = 0;
    14.         InvokeRepeating ("ChangeImage", 0.1f, frameRate);
    15.     }
    16.  
    17.     private void ChangeImage() {
    18.         if (currentImage == frames.Length - 1) {
    19.             CancelInvoke("ChangeImage");
    20.             Destroy (explosion);
    21.         }
    22.         currentImage += 1;
    23.         explosion.sprite = frames [currentImage];
    24.     }
    25. }
    26.  
    4. Change the variables (if you want)

    5. Make an Image and an empty GameObject with the script attached to it.

    6. Add all your frames to the list "Frames" in the inspector. Also, attach the Image to the GameObject that you created above.

    7. All done!!!
     
    dvvdvv and Xepherys like this.
  23. Bizarremax

    Bizarremax

    Joined:
    Sep 25, 2017
    Posts:
    1
    This works great! I was wondering if there was any way to repeat the gif so its non-stop?
     
  24. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    Just set currentImage back to 0 instead of calling CancelInvoke.
     
    Bizarremax likes this.
  25. JorgeAmVF

    JorgeAmVF

    Joined:
    Sep 14, 2017
    Posts:
    2
    It's also possible to deal with that in JS if you simply use the following piece of code provided in a solution available on this answer:

    Code (JavaScript):
    1. var frames : Texture2D[];
    2. var framesPorSegundo = 10.0;
    3. function Update()
    4. {
    5.     var index : int = Time.time * framesPorSegundo;
    6.     index = index % frames.Length;
    7.     GetComponent.< Renderer > ().material.mainTexture = frames[index];
    8. }
    9.  
    There's also this video showing the process.

    I tried the last solution provided here, but I don't know exactly why it was easier to deal with this issue by following this specific way which works following the same steps described by megarg.

    It's important to notice the GIF here will auto repeat.
     
    Last edited: Mar 14, 2018
  26. stn1414

    stn1414

    Joined:
    May 1, 2017
    Posts:
    1
    C# code

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class GIF_Manager : MonoBehaviour
    6. {
    7.     //frames
    8.     [SerializeField]
    9.     Texture[] Frames;
    10.  
    11.     // speed
    12.     [SerializeField]
    13.     float framesPerSecond = 10f;
    14.  
    15.     void Update()
    16.     {
    17.         // get index of frame
    18.         int index = (int)(Time.time * framesPerSecond) % Frames.Length;
    19.         // check if the Texture array don't equal null
    20.         if (Frames[index] != null)
    21.         {
    22.             // get Renderer of this gameobject
    23.             this.gameObject.GetComponent<Renderer>().material.mainTexture = Frames[index];
    24.         }
    25.     }
    26. }


    this website for disassembly GIF image online
    https://ezgif.com/split

    download your list of images and import to unity.
     
    Last edited: Apr 2, 2018
  27. SharksInteractive

    SharksInteractive

    Joined:
    Jan 27, 2018
    Posts:
    17
    If you just import an image sequence and then drag all the images into the scene view, unity automatically creates an anim and plays through your image sequence.
     
    thorichland likes this.
  28. hippogames

    hippogames

    Joined:
    Feb 5, 2015
    Posts:
    232
  29. fendercodes

    fendercodes

    Joined:
    Feb 4, 2019
    Posts:
    191
    You'll want to avoid calling GetComponent within an Update loop to avoid performance issues.
     
    JoelChala likes this.
  30. oneak

    oneak

    Joined:
    Oct 23, 2018
    Posts:
    2
    This works 2021 still on C#. All GIF Animators have been deprecated on Asset Store also YouTube tutorials. Thank you for this code!