Building the Star Wars Scroll Text in Unity

star wars styled text from unity

For those of you who may not know, I am a huge Star Wars fan. With all of the excitement going on lately around The Force Awakens (non-spoiler: It was great!) and just a couple of days left before 2016, I wanted to do a quick project to brush up on some of my Unity UI skills – so I decided to recreate the scrolling Star Wars opening text for virtual reality! Below, you’ll find my process and code so that you can follow along – or download the project from GitHub here.

My Developer Environment

Operating System: Windows 10 64-bit

Oculus Runtime / SDK: 0.8.0 (for PC)

Unity 5.3.1

Let’s Build!

The first thing that you’re going to want to do is set up a new Unity project with the defaults set for 3D development. I included Cameras, Standard Assets, and Visual Studio Tools asset packages, but I didn’t really end up building out anything with the Standard Assets package, so it’s up to you if you want to include these in your project.

Once you have your blank Unity project and a new scene created, the first GameObject that you’ll want to add is an Event System. The Event System object is the foundation for creating user interfaces with Unity, so I created one that lined up with the camera and added a Canvas to the Event System to start off the UI. Since this is going to be used in VR, go ahead and change the Canvas Render Mode to ‘World Space’ and set the main camera as the Event Camera.

With a user interface that you’re adding to an application or game, you’ll probably have to change things around to fit your environment. For this little sample, I set my Canvas width to 70 and height to 20, the Z position to 10, and changed the ‘Dynamic Pixels Per Unit’ to 10 instead of the default 1. Of course, since the Star Wars opener is at an angle, I also changed the rotation on the X axis to 55. You can change this value to whatever you’d like, since the script that we’re going to add will adjust itself to whatever this value is.

You may need to play with the exact values for width and height to suit your own application

You may need to play with the exact values for width and height to suit your own application

The next thing that I went ahead and did was add a panel to the canvas and change the background to black. There’s a little transparency to the panel by default, and when we add in the skybox at the end, this won’t be visible, but it was a good temporary step for making sure that all of the canvas elements were easy to see during testing. For now, this is the only change to make, but later on we’ll add our scroll script here.

Next, it’s time for the primary focus: the text! From the GameObject -> UI menu, add your text item as a child element of the panel. I made the width of the text just a little bit smaller than the Canvas (width = 50), but kept the height the same. Because we changed the dynamic pixel component on the Canvas, we can get away with making our text smaller, so I changed the font size on my text item to 3. Under Paragraph, make sure that the alignment is set to ‘center’ and ‘top’ for placement, and that your horizontal and vertical overflow are set to ‘wrap’ and ‘overflow’, respectively. Finally, change the text color to yellow, and your text will slowly start to be shaping up to be strong with the Force!

Unity text UI image

This image was taken before I decided on the final width of the panel – play around to make it your own!

Now that we have the basic GameObject components done, it’s time to add in the movement script. We want our text to scroll slowly up the slope drawn along the Z axis by our text rotation, and I decided that the cleanest way to do this was to attach the script to the Panel. This way, if we wanted to add other elements to scroll (such as a larger title text), we wouldn’t have to have multiple scrolling scripts potentially getting out of sync. I also didn’t want to attach it to the Canvas itself, because this would change where the whole text was located in the world, rather than providing a comfortable fixed location.

On the Panel object, create a new script (I use C#, but the script can easily be adapted for UnityScript) and call it ‘ScrollScript’. Save the script and open it up in your editor of choice – I use Visual Studio 2015 Community edition, which is available for free. In the script, I created two private variables: isScrolling and rotation, at the start of the ScrollScript class.

private bool isScrolling; // We'll use this for debugging
private float rotation;   // Default 55deg, but read in from canvas

To keep things tidy, the only thing in my Start() function is a method called Setup(), which I use to initialize my private variables. You can just add the following lines directly into the startup method if you prefer, or any other methods you might be calling at runtime if you’re working from an existing script.

// Start the scrolling effect on load
 void Start () {
        Setup();
 }
// Set up the initial variables
 void Setup(){
        isScrolling = true;
        rotation = gameObject.GetComponentInParent<Transform>().eulerAngles.x;
        Debug.Log("Parent rotation: " + rotation);
    }

There’s one part here that I probably should have changed, but since this is a learning opportunity, I decided to leave it in for now. When I’m getting the rotation value from the parent (Canvas) of the Panel, I set it in “degrees” – in this case, 55. If you use the line gameObject.GetComponentInParent<Transform>().rotation.x, this value is not 55, because transform.rotation returns a different quaternion value. You can read more about this in the Unity Transform documentation reference, and it’s why I use the .eulerAngles property instead.

After setting up the initial values, the only thing left to do for our script is add in the scrolling element, which you’ll want to place in Update() so that it gets called on every frame. This means doing a little bit of math, since we aren’t moving our text along one axis, but along the slope we created by changing the angle of the text. Our slope can be determined by calculating the sine and cosine of the angle we rotated our text on – which we don’t actually end up needing directly, but was helpful for debugging.

oculus vr in front of a notebook with math calculations

Yes, I did forget how to slope for just a second here

Before I actually update the text, I added in two input checks for some helpful functionality: the ability for the user to press “Escape” to quit the application, and the ability to stop and start the scrolling with the ‘A’ key. These are pretty simple checks in Unity, and just require a couple of extra if statements:

  // Check for starting or stopping
     if(Input.GetKeyDown(KeyCode.A))
     {
            isScrolling = !isScrolling;
            Debug.Log("Is Scrolling: " + isScrolling);
     }

  // Check if the user wants to quit the application
     if (Input.GetKeyDown(KeyCode.Escape))
     {
            Application.Quit();
     }

Finally, I use the sine and cosine of our angle through the Mathf class to calculate the new UI position of our Panel element from its current position, and update accordingly. Our Cartesian coordinates are on the Y axis and Z axis, so we update these to their new position by adding a scaled version of the sine and cosine values of our rotation. To change the speed, update .01f to a different scalar.

// If we are scrolling, perform update action
   if (isScrolling)
   {
       // Get the current transform position of the panel
       Vector3 _currentUIPosition = gameObject.transform.position;
       Debug.Log("Current Positon: " + _currentUIPosition);

       // Increment the Y value of the panel 
       Vector3 _incrementYPosition = 
         new Vector3(_currentUIPosition.x ,
                     _currentUIPosition.y + .01f * Mathf.Sin(Mathf.Deg2Rad * rotation),
                     _currentUIPosition.z + .01f * Mathf.Cos(Mathf.Deg2Rad * rotation));

       // Change the transform position to the new one
       Debug.Log("New Position: " + _incrementYPosition);
       gameObject.transform.position = _incrementYPosition;
           
    }

The whole script is fairly short:

using UnityEngine;
using System.Collections;

/**
* A script to reproduce the effect of the scrolling text in Star Wars
* By: Liv Erickson
* http://livierickson.com 
**/
public class ScrollScript : MonoBehaviour {

    private bool isScrolling; // We'll use this for debugging
    private float rotation;   // Default 55deg, but read in from canvas 

    // Start the scrolling effect on load
    void Start () {
        Setup();
    }

    // Set up the initial variables
    void Setup() {
        isScrolling = true;
        rotation = gameObject.GetComponentInParent().eulerAngles.x;
        Debug.Log("Parent rotation: " + rotation);
    }
	
    // Update is called once per frame
    void Update () {	
        // Check for starting or stopping
        if(Input.GetKeyDown(KeyCode.A))
        {
            isScrolling = !isScrolling;
            Debug.Log("Is Scrolling: " + isScrolling);
        }

        // Check if the user wants to quit the application
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }

        // If we are scrolling, perform update action
        if (isScrolling)
        {
         // Get the current transform position of the panel
         Vector3 _currentUIPosition = gameObject.transform.position;
         Debug.Log("Current Positon: " + _currentUIPosition);

         // Increment the Y value of the panel 
         Vector3 _incrementYPosition = 
          new Vector3(_currentUIPosition.x ,
                      _currentUIPosition.y + .01f * Mathf.Sin(Mathf.Deg2Rad * rotation),
                      _currentUIPosition.z + .01f * Mathf.Cos(Mathf.Deg2Rad * rotation));

         // Change the transform position to the new one
         Debug.Log("New Position: " + _incrementYPosition);
         gameObject.transform.position = _incrementYPosition;      
       }
    }
 }

Finally, there are just a couple of last things to do to finish off our scene. Because we’re trying to create an immersive experience that replicates the sensation of being in the Star Wars opening crawl, we want to add a skybox. Since we’re just doing a simple star-filled space background, you can use an existing skybox that you already have, or make your own. I picked a basic star image and did a few edits in Gimp 2 to make it a good texture for a skybox cube:

  • Desaturate colors to mimic the feeling of the original Star Wars crawl
  • Crop to a 1024×1024 cube
  • Run the ‘Make Seamless’ filter to avoid showing the edges of the box on each side

Once you have an image you’d like, go back to Unity and drag your star image into your project. In the Assets inspector, right click and create a new material called ‘Skybox-Stars’. Change the material shader to Skybox->6 Sided and set your star image to each of the textures on the side. Since we made the picture seamless, you can use the same .PNG for each side. Open the lighting window, and where you have the default skybox, change this to your new Skybox-Stars material.
A unity window with skybox material open

The last thing that I did to add to the overall feel of the Star Wars text was to change the text font to a new font that felt a little closer to Universa, the font used in the movies themselves. Since we’re just doing a quick project to distribute, I went for a free font from Google Fonts called Oswald.

To add a Google font into Unity:

  1. Go to www.google.com/fonts and find a font that you’d like
  2. Add the font to your collection
  3. Click the tiny arrow at the top and ignore Google telling you that you don’t have to download the font
  4. Click ‘Download as Zip’
  5. Extract the font into your Assets folder (I like to give it a folder of its own with the font name)
The fonts are now available to use if you return to your Text element and click the font option. You may need to play with a few options depending on how it looks – I originally had Archiva, but realized that condensed fonts don’t lend themselves nicely to VR, so I swapped to Oswald and prefer it greatly.
Lastly, in Player Settings, check that delicious ‘Virtual Reality Supported’ checkbox and pop on your headset! I like to pretend that the giant floating text was visible out of the Tantive IV windows at the beginning of ‘A New Hope’.
star wars styled text from unity

Related Posts

Leave a Reply

Your email address will not be published.