Developing cross-platform VR apps for Oculus Rift and GearVR

I’ve spent the past 2 months developing a virtual reality application for PC (Oculus Rift) and mobile (Samsung GearVR). I used Unity 5 and the Oculus PC ( and Mobile (0.5.1) SDKs. Here are some lessons learned that will save you time.

 Oculus PC and Mobile SDK can be used together

In Unity, you can use the two SDKs simultaneously. The Mobile SDK is under OVR>Moonlight (fun fact: Project Moonlight was the internal codename for the GearVR project). They share many resources, including the OVRCamera prefabs.

For example, if you use a OVRCameraRig in your scene, there is no additional work needed for it function properly on the PC or on mobile. It Just WorksTM

 Setup separate Unity project folders

Unity stores platform-specific data, like compressed textures in /Library. Unity’s texture compression runs as a slow, single-threaded process. Large textures like lightmaps can take a long time to compress, and can cause Unity to hang.

To make things worse, Unity 5 doesn’t store data for each platform separately. When you switch platform in your build settings, Unity overwrites the platform-specific data for the new platform. Each time you switch from PC to Android builds, Unity will have to re-compress every texture. This is a horribly inefficient workflow.

The solution is simple: have separate project folders for each build target, /MyVRApp-PC and /MyVRApp-Android but share resources between the two folders. Your /Assets and /ProjectSettings are the same for each platform. Keep them in one folder, say /MyVRApp-PC/ and use soft symlinks to give shared access to the Android folder. That way you don’t have duplicate copies of resources, but both projects can access the same shared set of assets.

Let’s assume you have a folder called /MyVRApp-PC On Mac, here are the steps:

mkdir MyVRApp-Android
cd MyVRApp-Android
ln -s ../MyVRApp-PC/Assets Assets
ln -s ../MyVRApp-PC/PlatformSettings PlatformSettings

On Windows, the instructions are similar

mklink /j Assets ..\MyVRApp-PC\Assets
mklink /j PlatformSettings ..\MyVRApp-PC\Assets

Now the only difference between the two folders will be the separate Library folders where Unity can store platform-specific data. To test a build on a different platform, just switch projects instead of switching build settings.

 High quality lighting

Unlike targeting the PC, realtime lighting–especially dynamic shadows–are too expensive for GearVR. Stick to baked lighting. If you followed the Oculus Mobile SDK integration instructions and copied over the Oculus PlayerSettings folder into your Unity project, you’ll have the Oculus default quality settings for Android. By default, they have no shadows. If you bake lighting while targeting Android, you’ll get poor results. Switch to the standalone PC platform when baking. Be sure to check your standalone quality settings before you bake; you should have hard and soft shadows enabled, and set your shadow quality to Very High Resolution.

While it’s recommended to use forward rendering on both PC and GearVR, you will get better results in your bake if you temporarily switch to deferred lighting. Every light in your scene is rendered as a per-pixel light, while most lights in forward rendering are vertex lit. Per-pixel lighting is highly desired, producing pixel-based effects like normal maps and shadowing.

However, this is extremely computationally intensive and should be avoided for realtime use (even on PCs). Just use deferred lighting during your bake, and switch back to the Android project when you’re done. When you switch back, Unity will have to recompress the freshly baked lightmaps; this may take some time.

 Quickly testing builds

I found several pain points in testing builds. On PC, it’s difficult to test a VR application inside the editor. In Unity 5.0.1f1, there is no way to test in Direct-to-Rift mode. You have to compile your build, and test externally. This is a slow process.

You can test using a monoscopic rendering inside the editor or separate debug camera, but that can be inconvenient and misleading. One solution is to use your Rift in Extended Mode and simply move the Game window over to that screen. Worth noting: this will be alleviated in the upcoming Unity 5.1 release (currently in beta for members of Unity Pro), which directly integrates the Oculus Rift into the Editor.

Alternatively, the SteamVR Unity plugin enables you to test on your Rift without leaving the editor, thanks to Valve’s method of using a layered compositor. Tangentially, I recommend reading Josh McCormick’s detailed analysis of the compositor on his blog Metaversing.

For GearVR, I have setup ADB to deploy builds wirelessly. Instructions for wireless builds can be found on Matt Ratcliffe’s excellent blog post on GearVR development. However, large projects are best deployed over USB. Even moderately sized 100MB APKs can take several minutes to be uploaded to your device over WiFi.

 Profiling on GearVR

Performance optimization on PC is straightforward – just be sure to check “autoconnect profiler” in your build settings. However, GearVR takes over your smartphone’s USB port and you cannot physically connect to the device while your app is running.

Instead, setup and connect ADB wirelessly. While not ideal for pushing large builds to your device, this is extremely useful for profiling. Once ADB is connected wirelessly, the Unity profiler can connect to the app on your phone.

 Next… Performance Optimization

That wraps up a brief overview of workflow tricks to speed up cross-platform development for the Oculus Rift and GearVR with Unity 5. Next, you should read my blog post on graphics performance optimization.


Now read this

VR camera rotation without nausea: a counterintuitive discovery

By now, this is obvious advice to any VR developer: you can positionally move a VR camera using a traditional gamepad thumbstick but any form of yaw rotation (mouselook or thumbstick rotation) causes extreme player discomfort. Stick yaw... Continue →