Building a VR App in 14 Days

A Designer’s First Time Building with Unity3D

At AOL Alpha we’re constantly exploring new and emerging platforms. One of the hottest new platforms is Virtual Reality so we’ve begun to experiment with creating experiences for VR. I was excited about this, so I spent some downtime between other projects researching how to design for VR using Unity3D engine. I also was presented with a challenge, one that sounded like a stretch, but could be extremely rewarding.

The challenge was: To build a demo version of a VR app on my own in two weeks. It needed to be functional with Google Cardboard, loosely based on AOL’s Autoblog site, it should have the basic functionality of allowing a user to select from a list of cars and visualize the inside of that car in 360˙, and it needed to be finished in time for AOL’s internal VR Summit in two weeks.

To a seasoned game designer this probably sounds like a doable task. I however, am not that person. I’m a mobile app designer, new to using Unity, with limited knowledge of scripting. I’ll be honest… I was a little worried.

I found out pretty quickly just how intimidating it can be to design and develop for VR. It’s like the Wild West! It lacks rules, structure, and most of all, information. It sometimes sometimes felt like fishing in a polluted swimming hole. You keep throwing out your line and reeling it in, only to find a bunch of trash stuck to your hook and have to start over again.

Nonetheless, I was eager to learn. So I set upon my adventure and kept at it with the end goal in sight. This is a brief overview of my approach — how I learned new skills, found solutions, and experienced the satisfaction of hacking a VR demo together with twigs and leaves.

Days 1–2: Flow, Shapes and Making Donuts

Planning
First off, we sat down as a team and made a quick sketch of the navigation. The plan was to keep it simple — just three types of scenes at most: a home page, a main menu, and a 360˙car interior maybe with some interactive panels.

The app’s main flow

Design options for the main menu
The main experience would simply be an image of the inside of the car placed on a skybox, a panoramic texture or photo that wraps around the scene. The main menu needed to look like a gallery of cars. This allowed for some creative flexibility — it could be a list, grid, panels, etc. It was obvious that the main menu should be the dictating force for the overall style. I just needed to decide how to arrange the gallery.

Unity had just released a series of amazing VR sample projects for the Oculus platform with impressively polished functionality like animations, click events, model shapes and meshes for creating a curved UI background. I was working in Google Cardboard though, so I found a nifty way to convert the demos from Oculus to a Cardboard-friendly version.

With these new tools at my fingertips, I wanted to test a few options for the app’s visuals and evaluate each option. Ease of development, since the short time frame, was a major factor to consider. A series of flat panels or curved panels seemed like the best options to display the car thumbnails.

Example of curved panels from the Unity VR demo (top) and flat panels (bottom)

I set up three starter projects:
1. Flat panel menu style using the Cardboard demo as a base.
2. Curved main menu style using the Oculus Unity demo as a base.
3. Curved menu style using the Cardboard demo as a base. This involved pulling out relevant parts of Unity’s Oculus demo and putting it into a fresh, Cardboard-based project. A little more work, but seemed like a worthwhile test.

Custom curved menu
I decided to start with the hardest method first, making a fresh version of curved menu style for Cardboard. Converting all of the Unity assets to match Cardboard’s specs was a struggle — they didn’t always match one-to-one and needed tweaking. Also, bringing in scripts from the Unity sample into my fresh build was tricky because they were linked to other objects or scripts in the original sample. With problems like this I felt like I’d need to revamp more things than I had time for. Too much tinkering, too many places for error, and the dreaded “Compiler errors have to be fixed” message greeted me repeatedly.

“Not again!” The compiler error message.

Curved menu
Making curved images and text in Unity relies on 3D meshes and models. There were meshes provided in the demo. But unfortunately, they weren’t quite the right proportion for my car images, so they needed be remodeled if I was going to make them usable. I spent an afternoon fussing with these strange looking fbx files in Cinema 4D, making alien spaceships and swirling donuts. It was fun work, but I ended up dropping the idea due to time constraints. If I had more time to learn how to make the models myself from scratch I think this could have been more efficient. It was also difficult to make the scripting tweaks to achieve the results I wanted. Making changes to the script often screwed up the naming conventions or broke other things in the scene.

Making alien donuts (modifying .fbx models in Cinema 4D)

Flat panels
Flat panels were a little tricky at first, but I figured out that I could use Unity’s UI buttons and fake them to look like images. I positioned each of the buttons side by side in front of the camera and gave each a 30˙ tilt on the Y-axis as they wrapped around the camera. I was able to set up a gallery of images pretty quickly. Buttons, by their nature in the Unity system, have a highlighted and pressed state that I could use to my advantage. I set the button so it would scale in size when the reticle passed over it. This gave me a nice pop feedback response. The button UI might also help me further down the line with click events. But I knew I would still have a good amount of work to do to get there.

Top view of flat panels, an early version. Each had a 30˙ tilt as they wrapped around the camera in the scene.

Evaluating and making a decision
By the end of Day 2, I had to choose a design path so I could start building the actual demo. My results were a bit mixed. I was disappointed to find that working with the beautiful Unity demos would be so cumbersome. Flat panels were easier to set up and the animations built into the button UI could be time saving.

Flat panels, it is!

Days 3–4: Scenes and Button Clicks

It was time to figure out how to implement some actions. Moving from one scene to another (i.e. from the main menu to inside a car) was the most critical interaction, so I started with this as my priority.

Scripting was unknown territory for me, so this part would be ambitious. Much of my initial searching revolved around click events on buttons. I figured maybe I could link a screen to that click event and create some sort of transition with the Unity Animator to move to the next scene. Then, maybe I’d end up making a menu manager that could associate that event with a screen. It seemed complex but sounded logical so I went for it.

Scene Switching
I was really struggling with how to move from one scene to another. It was feeling a bit bleak until out of nowhere, after dozens of Google searches, I found the term “Scene Switching” and the method, LoadScene. It was simply two lines of code that would handle switching from one scene to another with a button click. This turned out to be so much simpler than I’d imagined!

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class ButtonManager : MonoBehaviour {
      public void LoadScene(string sceneName) {
SceneManager.LoadScene (sceneName);
}

Unity 5.3, the current version as of this post, contains a new class called SceneManagement that controls scenes at runtime, so make sure you add “using UnityEngine.SceneManagement” to your script. Also, SceneManager.LoadScene replaced a previous class called Application.LoadLevel which is now deprecated. Beware, Unity is rapidly evolving with each new version and you’ll come across a ton of outdated information.

I created an empty game object on each page and added my scene switching script (which I called ButtonManager) to it. Then on each button (or car image), I simply added an OnClick event using that script, selected the ButtonManager.LoadScene method, and specified which scene it should change to. Presto! I could click an image of a car and look inside it.

ButtonManager script and the UI button OnClick event. Switching from an interior car scene to the Main Menu.

Days 5–8: Triggering a Button to Open a Panel

Next, I focused on the scenes inside the car. I wanted to include some basic information about the car (gas mileage, performance stats, etc), but I didn’t want to overwhelm the user with a ton of text — excessive reading in VR really sucks. I figured that smaller, more discreet interactive elements could be a good way to encapsulate this info. So my next big step was to place buttons inside the car that could open up these pop up info panels.

This shouldn’t be that hard right? A button that opens something else should be really standard functionality that everyone uses. So I set up a test panel and test button in my scene. After that, I pretty much ran into walls for three days.

My Button and Popup Panel inside the car

I spent three days trying to control the appearance of an object while hovering over a button or clicking a button. Using Unity’s Animator, I could designate an open and closed state for the panel and attach a button to it with the correct script to control this animation. I found out that it wasn’t actually that straightforward. There are a lot of moving parts here — which meant plenty of places to make mistakes.

I went through at least half a dozen different tutorial approaches — animations and scripts, clicking and hovering — none of them worked quite right. Then, late on Day 3, I found this forum topic titled: Show and hide a canvas on a button click. This response was marked as the best answer:

“NO CODE NEEDED”? Three days of trying out tedious routes, and it turned out all of this was already in the standard Unity script for OnClick events. So I hooked up my test button with an EventTrigger (PointerEnter and PointerExit) to hover and pop up the panel. It worked!

A few minutes later, I came down off my high when I realized the animation was terrible. Opening and closing the panel was functional, but harsh and jarring, and not at all graceful. It was obvious that I needed to attach an animation to it.

The simple but jarring pop up panel

This wouldn’t do, the next day I began searching for a new solution.

Revisiting the Animator
A clear head brought me to Day 8 and back to scripting and animation — the long method. As I thought about it more overnight, I had a bit of an ah-ha moment: I should be using a bool parameter. If I have one button that controls two states of the panel (open/closed) then a bool should check the current state of the panel so the button knows what to do. Is it open? Then close it. Is it closed? Then open it. My designer mind thinks about code quite crudely.

With this rough idea in mind, I found a new tutorial that felt remarkably similar to what I was trying to do. The tutorial called for a sliding menu, but I could sub-in my animation instead. It was written for an older version of Unity, so I’d have to adapt it. The important part was that there was a button that opened and closed a UI element — this is what I needed.

I set up new states for the panel with the Animator: Empty, Open, Closed and used the Animation tool and its keyframes to set up GameObject.IsActive (=0 when closed, =1 when open). I added a boolean parameter called isHidden and set it to true for the transition state open to closed, and false for the other transitions.

Animator states with transitions: Empty, Closed, and Open.
public class PopupManager : MonoBehaviour {
//Pulls in Animator states for Info Popup animator
public Animator myPanel;
public void ToggleMenu() {
bool isHidden = myPanel.GetBool("isHidden");
myPanel.SetBool("isHidden", !isHidden);
}
}

Then I created a new script, following the example in the tutorial. I attached the script to an empty game object and added an OnClick event to my button using the ToggleMenu method. After a little adjusting, it worked! Click the button and a panel pops up.

Day 9: UI Work and Refining Panel Animations

After nearly a week of building, I had my major button events working (scene switching and popup panels), but they still looked a little rough — they needed a little more work to smooth out the animation. I decided to work on the panels so they would open more gracefully. After experimenting with a few variations, I settled on adding an alpha transition, (from 0 to 1 when opening the panel) which made for a nice fade in and out. I rounded out the day by making photospheres for all the cars (via a 6-sided cube) and worked on creating the panel artwork in Sketch and exporting the assets.

Days 10–12: Smoothing out Scene Switching

With a little extra time on my hands, I revisited the scene switching — the transition still looked rough, so some fine tuning could do it some good. Since it didn’t involve an animation, I couldn’t use the same method that I used for the buttons and panels. I had to find another way, so I narrowed it down to two possibilities: fading to black between the scenes or use something called CrossFadeAlpha and CrossFadeColor.

I tried five different versions of scripts that other people were using and attempted to modify them for the project. I tried using variations of fade to black alpha floats with and without a coroutine (a timing function), placing a black UI square in front of a camera, and the illusive CrossFade methods that were supposedly embedded in Unity’s scripts. Most of these caused compile errors that I couldn’t fix and nothing was working for me.

Then I found this tutorial for fade in and out that had some elements of what I had already tried, but I decided to give it a shot. Just like the tutorial, I created a new script called Fading and copied it verbatim. I created a texture as directed (a 2px black square). Excellent, no compiler errors!

But this was just the first part. I also needed a second script to initiate the fade, and this is where I got stuck. Day 12 was spent fumbling with the code specified in the tutorial (namely the //fade out the game and load new level part). It didn’t look like it belonged anywhere in my project and it was causing compiler error after error.

Script from the tutorial to initiate the fade — figuring out what pieces I actually needed.

Wait a minute! It calls a method that I recognized, my old friend, Application.LoadLevel (a.k.a. SceneManager.LoadScene). I tried pulling out key parts of the tutorial script and putting it into my existing ButtonManager script. Remember that from way back on Day 4? It controls the scene switching. After some trial and error, I ended up with this modified script that would start a coroutine and call the Fading script from step one with a button click:

using UnityEngine.SceneManagement;
public class ButtonManager : MonoBehaviour
{
//Scene switching
public void LoadScene(string sceneName) {
SceneManager.LoadScene(sceneName);
}
//Fade out of the scene and add a new level
public IEnumerator ChangeLevel() {
float fadeTime = GameObject.Find("MenuManager").GetComponent<Fading>().BeginFade(1);
yield return new WaitForSeconds(fadeTime);
}
}

The button click was already implemented previously when I set up the scene switching, now it will use the Fade script. I adjusted the timing a bit so the fade would look smoother. Things were looking really good! I just needed to expand it to all the screens as my final step. I was nearly done with the legwork and it felt like the home stretch. I only had two days left.

Day 13: The Home Stretch and Last-Minute Surprises

Satisfied with my progress, it was time to finish up the car interior page. I added three buttons and three popup panels per car. But I discovered something alarming — all three of the buttons were opening the same panel. No! Slight panic ensued. But it’s ok, I had a few ideas.

I spent the morning trying to revamp the script and its parameters. I went through some trial and error trying to add a parameter to the toggle method, but realized that there was a simpler solution. I could just put the PopupManager script onto each of my panels (rather than on one empty game object), then assign the Info Popup animation. I created an OnClick event on each button and set each target panel and the ToggleMenu method. Finally, each button opened up its own panel. I was almost done.

Inspector shots for Panel (left) and Button (right)

When everything on the test pages looked good and the buttons were functioning properly, I expanded the remaining pages, added in the specific assets and finished the polishing. By the end of the day I was finished! (A day early, too!)

After struggling a bit, but learning a tremendous amount while navigating my raft through this bumpy adventure, I had a fully functional demo app that met all the specs that I originally set out to include. Adding in audio or video and expanding the experience to include more cars could be some next steps to tackle, as well as a curved variation of the gallery. There’s always more to learn and add!

Want to see the finished product? Check it out!

Big thanks to Carey Beth and Logan for their kind advice and edits.