How to get started with WebXR in Unity
WebXR is a technology with enormous potential, but at the moment it offers far worse tools to develop for it than standalone VR, where we all use Unity and Unreal Engine.
Mozilla, that is doing a lot for the immersive web, has so decided to develop a WebXR exporter for Unity, to let all Unity developers create WebXR experiences with the tool they already know well. This project dates from 2 years ago, but recently the WebXR plugin has been improved and updated.
As a Unity developer, I think that it is a very important enabling solution. Yes, there are some bugs, and the resulting code is not much modifiable (like it happens with A-frame instead), but finally, I can create WebXR experiences very easily, with the tools that I use every day.
I’ve spent the last days giving this pluging a try, so let me show you how to create your first WebXR experience inside Unity!
How to get started with WebXR in Unity – Video Tutorial
I made a very complete Video Tutorial showing you step by step how to create your first cube in WebXR inside Unity. I go from the requirements to the final deploying of the project. I think this video is a very good guide to begin your journey inside WebVR development, so watch it now!
How to get started with WebXR in Unity – Textual Tutorial
Ok, let’s dig into Unity WebXR development!
Requirements
First of all, be sure to have all the tools required to follow this tutorial. You’ll need:
- Unity game engine (of course). If you download the WebXR plugin from its GitHub page, you can have Unity 2018 LTS (2018.4.20), while if you get it from Unity Asset Store, you must have at least Unity 2019.3.4. I downloaded Unity 2019.3.11 for this project. Be sure that your Unity installation has WebGL support installed, otherwise use Unity Hub to add it;
- A web server, with SSL certificates. This may be a local server on your pc (Apache, IIS), a server on a local virtual machine, or a web server that you own. From my experience, launching the WebXR page on your disk opening it with your browser doesn’t work for security reasons, so you had better have a server. How to do that is not the purpose of this tutorial, but I can advise you to use your webspace if you have one (e.g. I have the one of this blog), or use Glitch, or install a LAMP/WAMP server on your machine (in this case, don’t forget the SSL certificates).
How to set up the environment
Open Unity, and create a new project. When prompted what kind of project to create, select Universal Rendering Pipeline (URP) or Lightweight Rendering Pipeline (LWRP), depending on your Unity version. This is not a mandatory step for WebXR, but it is the format chosen by Mozilla for its demo, so we’ll stick with it.
After the project has been created, go to the Asset Store tab and look for WebXR Exporter. You’ll find a plugin by Mozilla. Click on it and import it into your project.
UPDATE (2021.12.24): My friends from Crazy Kung Fu suggest that you now use the Package Manager to get the package, because on the Asset Store it is not updated
Select File->Build Settings…->Player Settings, being sure that the platform selected is still PC, Mac&Linux Standalone. In the settings window that will pop up, go to the XR Settings group item and click on “Virtual Reality supported”. This will make sure that we can correctly preview the content inside Unity.
To adjust also the input inside the editor, you have to substitute the content of the file <Project_root_dir>/ProjectSettings/InputManager.asset with the ones provided by Mozilla: https://raw.githubusercontent.com/MozillaReality/unity-webxr-export/master/ProjectSettings/InputManager.asset. Remember that you must do this operation outside Unity, because the Project Settings are outside the Assets folder. You can use File Explorer to substitute the whole file, or Notepad++ to substitute its contents.
Now you can return to the File->Build Settings… dialog and select the platform WebGL, then hit “Switch Platform” and let Unity switch to WebGL mode.
The last step is to return to the Player Settings, and now go to the “Resolution And Presentation” options group. In the section “WebGL Template”, select WebXR. Then add a “Description” and a “Name” of your app as you prefer.
We are all set and we can start developing!
Plugin Analysis
The Plugin adds the WebGL and WebXR folders to the project. The exporter basically creates a special type of WebGL application that supports virtual reality, that’s why there are both directories.
The most interesting code is inside the WebXR folder:
- The Config folder contains some scriptable objects with inside the mapping between Unity Input and the VR actions. Mozilla already provides two samples, but we are free to customize the input received by the application as we wish;
- Models contains the models used for both hands, plus their animations. Notice that Mozilla already provided one simple hand model plus a basic “grip” animation, but you’re free to use the hand model that you want;
- Prefabs owns the main prefab used by WebXR applications, the one of the WebVR camera (more on this later on);
- Samples contains the Desert scene, from which you can learn how to perform some basic interactions with objects (I advise you to give it a look);
The WebXRCameraSet prefab contained in Prefabs folder is the most important thing that you will use. It is a barebone prefab letting you have your head and hands in VR, but you can start from there and customize everything as you want. You can see that every hand has an associated Animator and RigidBody, and its children objects are the model and the bones of the hand. You can substitute the models, you can add new hands animations, and everything would still work. Notice that the default prefab DOES NOT TRIGGER ANY ANIMATION associated with your fingers movements, but you have to script all by yourself (more on this later in the tutorial).
The WebXRController script associated with each hand is the one that you can query to obtain the status of that hand, and it gets an InputMap parameter through which you can decide how to map standard Unity input to VR input (more details at this page).
Let’s play!
To have a taste of WebXR, you can try the demo scene, located at Assets\WebXR\Samples\Desert. The scene is called “WebXR”.
If you open it, you see exactly the same scene advertised on Mozilla’s website. You can put on your headset, press the play button in Unity, and if everything is configured correctly, you would see everything in VR. You can take the cubes and the spheres that are close to you and interact with them. You could also build it and enjoy this VR world.
But we don’t like this fancy scene… we like gray cubes, isn’t it? So follow me, and I’ll let you create some beautiful WebVR gray cubes!
Your first WebXR experience in Unity
Create a new scene in your folder Assets\Scenes and call it GrayCube. If you don’t know how to create something in Unity, start by clicking the right button of the mouse in the Project Tab.
When you’re done, open the GrayCube scene and as a first thing, remove the Main Camera. Take the prefab WebXRCameraSet from the Assets\WebXR\Prefabs folder and put it into the scene. Basically, we’ve substituted the standard camera with the VR camera. Notice that you don’t have to raise this camera from the origin since the camera will automatically go to the right height when the program gets executed (look at the script WebXRManager).
Now it’s time to add the cube. In the Hierarchy Tab, click with the right button of the mouse and select 3D Object -> Cube. Now move the cube where you want using its 3D arrows inside the Scene Tab.
And it’s over! Easy peasy! You’ve done your first WebXR experience in Unity! Save the scene, press the Play button and you can see the whole scene and your hands inside your headset :O
Your first interactive WebXR experience in Unity
We all love seeing gray cubes in Unity, and this is what I love to do as tutorials (like for instance in this tutorial on how to get started with Oculus Quest in Unity). But the problem of this experience is that it is probably too much static, and even your hands don’t perform any kind of animation.
As I explained before, the prefab offered by Mozilla gives you just very basic functionalities, with the possibility of expanding it as you want. Let’s take inspiration from the example and add some interactions.
So, let’s make the hands open and close. Go back to the Project Tab and create a new C# Script in Assets\Scripts and call it CloseHands.cs. Add it to both the WebXRCameraSet\handL and WebXRCameraSet\handR gameobjects in the scene, by dragging it onto them.
Now open the script in Visual Studio by double clicking on it and substitute its code with this one
The code is fairly simple: we get the Animator associated with the hand and also its WebXRController behaviour. Every frame, we query the WebXRController for the status of the buttons, and we use the Animator to change the shape of the hand depending on this. The animation that the Animator uses by default is a simple “close hand” animation provided by Mozilla, and the system shows a particular frame of that animation depending on the status of the buttons. The more you press your Grip button, the more the hand closes. If you press the Trigger button, the hand closes completely instead.
That’s it. Press Play, and now you can see that you can close your hands using the buttons in your controllers!
Let’s go deeper
Let’s add another simple functionality that colors the cube!
Back to the Project tab, create a new script in the Scripts folder and call it ColorCube.cs . Then add it to your left hand by dragging it onto the WebXRCameraSet\handL gameobject in the Hierarchy. The code of the script should be this one:
What we do in this script is: if the WebXRController detects that you’ve pressed the Trigger, it looks for the Cube in the scene, and substitute the main color of its main material with a random color. Expert Unity developers probably would comment that using GameObject.Find() every time is a bad practice, but here we’re just making a sample, so it’s ok for the sake of simplicity. If you wonder why I don’t use material.color, it is because we are in URP and there is no “_MainColor” in the standard Lit material.
Save everything, press Play and now you can see that as soon as you press the trigger button of your Left hand, the cube changes color!
The problem is that if you keep the button pressed, it keeps changing the color every frame, creating a discotheque effect. If you want that for every time you press the trigger, the color changes only once, the code should be this one:
It is identical to before, we’ve just used GetButtonDown instead of GetButton.
Press Play and you should see that everything is fixed now. You can close both your hands and when you press the trigger button on your left hand, the cube changes color in the right way!
(While doing my tests, I’ve noticed that sometimes the GetButtonDown method gets stuck and works only once. This looks like a bug of the plugin, and I hope it will be fixed soon).
Deploy your game
Now that you’ve created this killer app, it’s time to deploy it. So head to File-> Build Settings… , remove the default scene in the “Scenes To Build” list and add the current one by using the Add Open Scenes button. After that, press the Build button. Select where the project must be built and then go watching some panda videos on Youtube, since WebXR builds can take a lot of time. Notice that Mozilla advises using “Build and Run” so that you can test your application on the fly without messing with web servers, but it has never worked for me. For this reason, I advise you to use this alternate approach.
When the build has finished, you have a folder containing your WebXR experience, with an index.html file and a lot of other stuff. Take this folder and put it inside your web server (local or online).
After that, try to access it by simply going to the web address of your just built index.html file with your browser. But remember that:
- You must use a WebXR-compatible browser (Chrome and Firefox are ok, Edge should be as well);
- If you don’t have a web server and try to just access the index.html file on your hard drive with a browser, security restrictions will prevent your app from working;
- If you access your webpage using http and not https, it won’t work. Force the use of https by typing https:// in your URL;
- If when you’re prompted by Firefox if you want to allow VR on that page, you don’t click on “Allow” in time, it won’t work. My advice is to click on “Remember my choice” and then on Allow in the authorization popup, then reload the page. This way you are sure that every time you load your experience, VR will always be enabled since the beginning.
If you don’t see any popup saying that you’ve not a VR headset or a VR compatible browser, everything is ok.
Click on the Headset icon in the bottom-right corner of your browser and BAM! You’re in WebXR!
Test the interactions, and you see that you’re able to move your hands and make the color of the cube to change. You did it!
Further references
Now it’s your turn to unleash the power of Unity to create Web experiences!
You can examine the Desert sample to learn how to implement basic interactions with objects, or you can examine the source code of the plugin, plus its complete documentation, at its official page: https://github.com/MozillaReality/unity-webxr-export
I hope you enjoyed this tutorial, and if it is the case, send me many hugs, subscribe to my newsletter to not miss my future posts, and donate on Patreon to support my hard work!
(Header image by Mozilla Foundation)
Disclaimer: this blog contains advertisement and affiliate links to sustain itself. If you click on an affiliate link, I'll be very happy because I'll earn a small commission on your purchase. You can find my boring full disclosure here.