1. We've introduced thread tags, search within a thread and similar thread search. Read more here.
    Dismiss Notice
  2. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice
  3. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  4. We've released our first Timeline Experimental Preview, our new tool for creating cutscenes and more! To check it out click here.
    Dismiss Notice
  5. Unity 5.5 is now released.
    Dismiss Notice
  6. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  7. Unity 5.6 beta is now available for download.
    Dismiss Notice

Movie Player for Indie Users

Discussion in 'Made With Unity' started by wbokunic, Jun 20, 2010.

  1. wbokunic

    wbokunic

    Joined:
    Dec 17, 2009
    Posts:
    43
    I've seen a few threads where users of Unity Indie were wanting to play movie clips and such. Since this is a Pro feature, you can't, obviously, play movies in Unity Indie. However, you can play a series of stills in Unity Indie to create the illusion of video.

    So, what I've done is created a [crude and] simple-to-use script for Unity Indie users to play movie clips. Here's the web demo (note - you might need to refresh the page after the initial load for the video to be in-sync).

    [​IMG]

    https://dl.dropbox.com/u/7181231/builds/MovieScene/moviescene.html

    Before you use:

    1) Compress your video so that it is exactly a certain number of frames. It cannot be something like 29.97 frames per second. It needs to be something like 30 frames per second.

    2) Use a program (like VirtualDub) to convert the video into a series of still images.

    3) Use a program like Audacity to strip out the audio into an .mp3 or something similar.

    Now that we've cleared that out of the way, here's how you use it!

    How to use:

    1) Drop the script on an object, preferably a plane (though it can be anything). Also make sure to set a material. It can be a blank texture though.

    2) Configure the options to your liking. Set the "Number_of_stills" value to the number of "Movie_stills" you have (there's probably a way to grab this number, but I got a bit lazy lol). Determine if you want the video to loop, set the fps and/or attach an audio file.

    3) Make sure "sync to VBL" is enable in the quality settings. Otherwise the video and audio might get out of sync (only needed if you use an audio clip).

    4) Load the level and see how it runs!

    I tried to give the user a few options. So it is optional if you want to use audio or not, as well as if you want the video to loop or not. If the movie ends before the audio does, the audio will stop as well too. It's also set up in a way that almost anyone could go in and tweak it for their own needs (enabled when the user presses "E" on it for instance).

    Do heavily note though: This method is a pain. The video demo I recorded was roughly 9 seconds long, meaning I had over 270 still images I needed to manually drop in one at a time. So I'd use this script sparingly.

    [​IMG]

    Code (csharp):
    1. var movie_stills : Texture[] = new Texture[1];
    2. var number_of_stills = 1;
    3. var Loop = false;
    4. var fps = 30;
    5. var Sound : AudioClip;
    6.  
    7. private var stills = 0;
    8. private var play = true;
    9.  
    10. function Update () {
    11.     if(fps > 0){
    12.         if(play == true){
    13.             Player();
    14.         }
    15.     } else {
    16.           Debug.LogError("'fps' must be set to a value greater than 0.");
    17.     }
    18. }
    19.  
    20. function Player(){
    21.     play = false;
    22.     if(Loop){
    23.         if(stills > number_of_stills) {
    24.             audio.Stop();
    25.             audio.clip = Sound;
    26.             audio.Play();
    27.             stills = 0;
    28.         }
    29.     } else {
    30.         if(stills > number_of_stills) {
    31.             audio.Stop();
    32.             stills -= 1;
    33.         }
    34.     }
    35.     var MainTex = movie_stills[stills];
    36.     renderer.material.SetTexture("_MainTex", MainTex);
    37.     stills += 1;
    38.     var fps_fixer = fps*3;
    39.     var wait_time = 1.0/fps_fixer;
    40.     yield WaitForSeconds(wait_time);
    41.     if(!audio.clip){
    42.         if(Sound){
    43.             audio.clip = Sound;
    44.             audio.Play();
    45.         }
    46.     }
    47.     play = true;
    48. }
    49.  
    50. function Start ()
    51. {
    52.     audio.loop = false;
    53.     number_of_stills -= 1;
    54. }
    55.  
    56. @script RequireComponent(AudioSource)
     
  2. Blacklight

    Blacklight

    Joined:
    Dec 6, 2009
    Posts:
    1,206
    You've beaten the system! :D

    It isn't the most elegant way of doing things, but you did a good job.
     
  3. GeneralGrant

    GeneralGrant

    Joined:
    Jun 10, 2010
    Posts:
    977
    amazing!




    I see you...
     
  4. wbokunic

    wbokunic

    Joined:
    Dec 17, 2009
    Posts:
    43
    Yes, you see me being very tired lol.

    I actually made this for doing simple animations of images, versus doing full blown sprite support, since this is easier to manage. Figured I'd upgrade it a bit for full movie support and release it since quite a few Indie users have requested it.
     
  5. Caliber-Mengsk

    Caliber-Mengsk

    Joined:
    Mar 24, 2010
    Posts:
    678
    hmmm... I wonder how easy it would be to make a simple VB app that would use FFMPEG to convert the video to frames, and the audio to mp3/ogg...


    ....... May have to look into this.

    Unfortunately, this method would make really really large downloads if you had a lot of video.
     
  6. wbokunic

    wbokunic

    Joined:
    Dec 17, 2009
    Posts:
    43
    Yeah. The recorded video was about 5 MB. Breaking up all the frames into images and the audio as well resulted in about a 1 mb increase. So not much different from using real video. Just use it sparingly.
     
  7. Imari

    Imari

    Joined:
    May 26, 2010
    Posts:
    24
    Whoa, thank you!
     
  8. rtumelty

    rtumelty

    Joined:
    Dec 11, 2011
    Posts:
    11
    Hi, great script! The amount of setup seemed rather extreme though. I've adapted it so that the script will automatically load the images from a subfolder of Resources. At the moment, that's done at runtime - I may change it so that the user can force a load from within the editor at some point (for that little less overhead). The audio clip must still be added manually, but with a minor change it can load an audiofile from the same folder as the image sequence. I ported it to C# also, mostly out of personal preference. I've tested it on PC and Android. You can find the code below.

    A note on my implementation: it requires that you store the images in a subfolder of Assets/Resources. Anything here will be added to the build, whether it's used or not, as the engine ignores the Resources folder for optimising. So if you decide not to use any resources, make sure to delete them from the folder before building to keep your filesize down!

    But yeah, great workaround!

    Ronan Tumelty

    Code (csharp):
    1.  
    2. // Original script by wbokunic - http://forum.unity3d.com/threads/52001-Movie-Player-for-Indie-Users
    3. // Modified C# version by Ronan Tumelty
    4.  
    5. using UnityEngine;
    6. using System.Collections;
    7. using System.IO;
    8.  
    9. [RequireComponent(typeof(AudioSource))]
    10. public class VideoPlayer : MonoBehaviour {
    11.     Object[] movie_stills;
    12.     int number_of_stills = 0;
    13.     public bool loop = false;
    14.     public bool playOnStart = false;
    15.     public int fps = 30;
    16.     public AudioClip sound;
    17.     public string resourceSubfolder = "";
    18.      
    19.     private int stills = 0;
    20.     private bool play = false;
    21.     private bool loaded = false;
    22.      
    23.     void Update () {
    24.        
    25.         if (!resourceSubfolder.Equals("")  !loaded) {
    26.             StartCoroutine(ImportVideo());
    27.         }
    28.        
    29.         if(fps > 0){
    30.             if(play == true){
    31.                 StartCoroutine(Player());
    32.             }
    33.         } else {
    34.               Debug.LogError("'fps' must be set to a value greater than 0.");
    35.         }  
    36.     }
    37.      
    38.     IEnumerator Player(){
    39.         play = false;
    40.         if(loop){
    41.             Debug.Log("looped. stills: " + stills + ", length: " + movie_stills.Length);
    42.             if(stills >= movie_stills.Length) {
    43.                 audio.Stop();
    44.                 audio.clip = sound;
    45.                 audio.Play();
    46.                 stills = 0;
    47.                 Debug.Log("restarting. stills: " + stills);
    48.             }
    49.         } else {
    50.             if(stills > movie_stills.Length) {
    51.                 audio.Stop();
    52.                 stills -= 1;
    53.             }
    54.         }
    55.        
    56.         if (stills >= 0  stills < movie_stills.Length) {
    57.             Texture2D MainTex = movie_stills[stills] as Texture2D;
    58.             renderer.material.SetTexture("_MainTex", MainTex);
    59.             stills += 1;
    60.             int fps_fixer = fps*3;
    61.             float wait_time = 1.0f/fps_fixer;
    62.             yield return new WaitForSeconds(wait_time);
    63.             if(!audio.clip){
    64.                 if(sound){
    65.                     audio.clip = sound;
    66.                     audio.Play();
    67.                 }
    68.             }
    69.             play = true;
    70.         }
    71.     }
    72.    
    73.     public void Play() { play = true; }
    74.     public void Pause() { play = false; }
    75.      
    76.     void Start ()
    77.     {
    78.         audio.loop = false;
    79.         number_of_stills -= 1;
    80.     }
    81.    
    82.    
    83.     IEnumerator ImportVideo() {
    84.         movie_stills = Resources.LoadAll(resourceSubfolder, typeof(Texture2D));
    85.         loaded = true;
    86.         if (playOnStart)
    87.             play = true;   
    88.         yield return null;
    89.     }
    90.    
    91.     public void UnloadFromMemory() {
    92.         play = false;
    93.         audio.Stop();
    94.        
    95.         foreach (Object o in movie_stills) Destroy(o);
    96.     }
    97. }
    98.  
     
  9. ThomQ

    ThomQ

    Joined:
    Nov 23, 2010
    Posts:
    297
    Great Job, Going to test it on mobile tonight, let you know the results!
     
  10. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    490
    any way to use actual MP4 video from resource folder, in place of still images.
     
  11. TAGGEDGAMES

    TAGGEDGAMES

    Joined:
    Mar 6, 2013
    Posts:
    43
    Wow great job.
     
  12. moss18

    moss18

    Joined:
    Jan 14, 2013
    Posts:
    1
  13. SaudAli3

    SaudAli3

    Joined:
    Nov 5, 2013
    Posts:
    2
    Can We use mp4 video file instead of still images?