Unity: How to use a GUI Texture to play fullscreen videos
Posted by Dimitri | Apr 19th, 2011 | Filed under Programming
Warning: this tutorial only works with Unity Pro because the free version doesn’t come with video playback support. The code was created and tested with Unity version 3.3. It won’t work for versions 2.6 and below (requires some adaptation).
This Unity post explains how to set up a GUI Texture at the Unity editor and the code necessary to play a fullscreen video, that can be used for the studio logo animation at the beginning of the game, the game’s intro or any other video that needs to take the whole screen. It also explains how to properly scale the video based on the screen dimensions. At the end of the post, a Unity project featuring all the code explained here is available for download.
Before setting the scene or programming the script, you have to create or find a video file from the internet to use with Unity. Here’s a list of Unity’s supported video formats. It’s basically what the QuickTime Player supports (without additional codecs).
After getting the video file, add a folder named Resources in your Project tab. Just right-click anywhere inside and select New->Folder. This is where the video files should go, just drag and drop them inside this folder.
With the videos inside Unity, prepare the scene with the required Components needed to make the video playback work, which are:
- A GUI Texture, that will hold the video to create a handle its attributes.
- An Audio Source to play the video’s audio.
- A script, that will set up the video to be played at the GUI Texture with sound, making the necessary adjustments to fit the video on the screen.
These components are going to be added at the Main Camera game object, which already comes in every Unity3D scene. After adding them, you will end up with something like this:
The PlayVideo script responsible for setting up and starting the video playback. Here’s the code:
using UnityEngine; using System.Collections; [RequireComponent (typeof (GUITexture))] [RequireComponent (typeof (AudioSource))] public class PlayVideo : MonoBehaviour { //the GUI texture private GUITexture videoGUItex; //the Movie texture private MovieTexture mTex; //the AudioSource private AudioSource movieAS; //the movie name inside the resources folder public string movieName; void Awake() { //get the attached GUITexture videoGUItex = this.GetComponent<GUITexture>(); //get the attached AudioSource movieAS = this.GetComponent<AudioSource>(); //load the movie texture from the resources folder mTex = (MovieTexture)Resources.Load(movieName); //set the AudioSource clip to be the same as the movie texture audio clip movieAS.clip = mTex.audioClip; //anamorphic fullscreen videoGUItex.pixelInset = new Rect(Screen.width/2, -Screen.height/2,0,0); } //On Script Start void Start() { //set the videoGUItex.texture to be the same as mTex videoGUItex.texture = mTex; //Plays the movie mTex.Play(); //plays the audio from the movie movieAS.Play(); } }
The code works by first requiring an AudioSource and a GUITexture to be already attached to the game object, if they aren’t, they will be added with the script (lines 4 and 5). Then, a GUI Texture, a Movie Texture and an Audio Source objects are declared, and will serve as a handles that allows to change programmatically the area of the screen where the video should be rendered, the video file to read, and an Audio Source to play sound of the video (lines 10 through 14). The string at line 16 is used to retrieve the video file by it’s name from the resources folder.
At the Awake() method, everything that is required for successfully playing the movie is done: the attached GUI Texture and Audio Source components handles are acquired (lines 21 and 23), the movie file is loaded at line 25; the Audio Source clip is set to be the audio of the movie (line 27) and finally, the GUI Texture is set to render the movie using the whole screen and stretch it, if necessary (line 29).
The Start() method only sets the texture inside the GUI Texture to be the loaded movie texture (line 36) and starts the video and audio playback (lines 38 and 40).
Don’t forget to set the movieName variable at the Inspector, so it can be loaded from the Resources folder or else it won’t work, because nothing will be loaded.
As the reader might have noticed, this code will not take the video’s aspect ratio in consideration and will stretch it so it can take the whole screen. To successfully maintain the aspect ratio of the videos, read the following sections below.
Stretching the movie’s width and how to find the new height (letterbox)
This is one of the most typical situations, specially for PC and Mobile games, where there is a large number of screen resolutions and the video has a widescreen format. To make a widescreen video fit a 4:3 or 5:4 monitor, we know that the width of the video must be equal to the width of the screen. That leaves the height of the video and the position of the video at the Y axis to be calculated based on the screen’s width. To do that, the following equation will be used in the code:
- video height = screen width / video’s aspect ratio;
- video Y position = screen height + video height;
The problem is that the GUITexture pixelInset attribute in Unity 3.3 must have the X value positive, while the Y, width and height must be negative so the video can be properly scaled into the screen.
This means that the above equations must compensate the screen width when turning them into code, so the video can be correctly scaled and positioned. So, to properly scale a video based on it’s width, line 29 of the above code will be replaced by:
//replace line 29 with the following: float newHeight = -(Screen.height-(Screen.width/(mTex.width/(float)mTex.height))); float yOffset = (-Screen.height-newHeight)/2; videoGUItex.pixelInset = new Rect(Screen.width/2, yOffset,0,newHeight);
Stretching the movie’s height and how to find the new width
This is one of the cases where you want to have a 4:3 video framed by two columns in a 16:9 screen. This time, the video’s height is going to be the screen’s height. What we need to figure out is the width and the position of the video at the X axis that has to be calculated based on the screen’s height. Here’s the equation that does that:
- video width = screen height * video’s aspect ratio;
- video X position = Screen.width + newWidth/2;
Again, it’s required to compensate the pixelInset Y, width and height values with the screen width, so that they are filled with negative values. This leads to the following code (replacing 29):
//replace line 29 with the following float newWidth = -(Screen.width-(Screen.height*(mTex.width/(float)mTex.height))); float xOffset = (Screen.width - newWidth)/2; videoGUItex.pixelInset = new Rect(xOffset, -Screen.height/2,newWidth,0);
If that appears to be confusing, try changing the pixelInset values of a GUITexture at the inspector and it will become much more clear.
Downloads
- fullscreenvideo.zip (7.83 MB) For instructions, please refer to the README.txt file.
Great tutorial. I wonder if this will work on mobile devices (iOS, android)
I’ve spent the last two days trying to figure out how to render models/meshes in front of a movie texture… have you tried this?
I am beginning to think it isn’t possible. Is the better approach to try getting the movie texture on a plane playing with it set back from the camera some?
I essentially want a movie texture running in the background and bring up the UI from there to include some geometry animating.
If only Unity supported Scaleform :(
Nope, I’ve never tried it. Maybe you could, as you described, use a plane for the video and render the models in front of it. Additionally, you could put the plane at a new layer and use a dedicated camera that renders only that layer.
Don’t forget that Unity’s GUI Texture component always appears on the top of the Z buffer. So, nothing can be in front of a GUI Texture.
Maybe this tutorial will help you get some ideas, since it describes how to set different cameras for specific GUI elements. Another thing that could be done is, instead of using the GUI Texture component, render video using the GUI class.
@tstpierre
did you accomplish it ?
love you!! thanks!!
Thanks for your tutorial.
I could not get the video to play even after following all steps and checking everything. the main question still was how can I use the FullScreenControlMode option here in this script. I wanted to use the .full mode so that I can have all the controls for my video.
Thank you! This was a helpful post!
Thanks, good theme
Hi! Thanks for the post! Very helpful. I thought issue with background sounds after playing video in game published for web player. Initially I thought it is related to the video player but it appeared to an issue with the sound. Great job! Keep it up.
Thanks for the info!
Thank you for this helpful post. I am trying to combine this with a OnMouseDown trigger on an object, so that clicking objects temporarily launches different full screen movie textures as GUI. do you have any hint how I could do that?
Do not forget to install QuickTime before importing mov file into project. Here is small instruction how to import and play video in Unity3d: http://druss.co/2015/05/unity3d-how-to-play-video-in-unity-project-movietexture/