loading...
Cover image for Making Your First VR App With React360

Making Your First VR App With React360

flippedcoding profile image Milecia McG ・7 min read

It's impossible to be in the tech community and not know about the rise of virtual reality or VR. There are gaming systems, mobile apps, and web apps that take advantage of the features that VR has to offer. The great thing is that if you are familiar with the React ecosystem, then you can jump right into building VR apps! React 360 is a library that uses a lot of React Native functionality to build VR apps and it's a great way to get started as a VR developer.

We'll go through the setup of a simple interactive VR app using React 360. By the end of this tutorial, you should feel ready to start adding complexity to your VR app and make it more user-friendly. I'll give you a few ideas at the end just in case you need a little jump start.

Install React 360 CLI

The first thing you need to do is install the React 360 CLI. This will give you access to the commands you'll need to build a VR app. So open your terminal and navigate to the folder you want to create this project in. Then run this command.

npm install -g react-360-cli

This installs it globally so you won't have to do this again for future projects. The only reason you're in the project folder is to make the next step easier. Now you'll create a new VR project called "vr-project" (so creative) with the following command.

react-360 init vr-project

Now you have a brand new VR app built on React 360! To see what it looks like in your browser, you can use the terminal to go inside of the vr-project folder and then run npm start. It should tell you where to go in the browser, but in case it doesn't, try navigating to http://localhost:8081/index.html. You should see something like this.

https://miro.medium.com/max/1600/0*QSZfhmAIYwFAqEyr.png

Let's go through the project and talk about the code. The main files you'll focus on are index.js and client.js. There are four main parts of the index.js file: imports, the class, styles, and registering the component. We import React so that we can work with it's class functionality and we import some things from React 360 so we create our VR world.

import React from 'react';

import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} from 'react-360';

export default class vr_project extends React.Component {
  render() {
    return (
      <View style={styles.panel}>
        <View style={styles.greetingBox}>
          <Text style={styles.greeting}>
            Welcome to React 360
          </Text>
        </View>
      </View>
    );
  }
};

const styles = StyleSheet.create({
  panel: {
    width: 1000,
    height: 600,
    backgroundColor: 'rgba(255, 255, 255, 0.4)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  greetingBox: {
    padding: 20,
    backgroundColor: '#000000',
    borderColor: '#639dda',
    borderWidth: 2,
  },
  greeting: {
    fontSize: 30,
  },
});

AppRegistry.registerComponent('vr_project', () => vr_project);

The class syntax should look familiar from React and the components are similar to those used in React Native. You use the View component to render different parts of the VR environment and you change the way they look through the style attribute and the StyleSheet which is similar to what is used in React Native and it feels a lot like regular CSS.

The Text component is exactly what it sounds like. You can display text to a user and that text can be dynamic to display different kinds of data. At the very end, you have to register the class to the client so it will be rendered. In the client.js file, you'll notice that the init function creates a new instance for your VR project and uses the class from the index.js file to set the render method for your project. Then it sets the environment of the VR project to a panoramic image. Lastly, it runs the init function in the browser window.

import {ReactInstance} from 'react-360-web';

function init(bundle, parent, options = {}) {
  const r360 = new ReactInstance(bundle, parent, {
    fullScreen: true,
    ...options,
  });

  r360.renderToSurface(
    r360.createRoot('vr_project', { }),
    r360.getDefaultSurface()
  );

  r360.compositor.setBackground(r360.getAssetURL('simmes-start-screen.jpg'));
}

window.React360 = {init};

Now that you know the basics of how the React 360 app works, you can start making your own custom VR app. We'll go through a few of the things you can add to your project.

Add assets for the background

You can change the background for your environment to any panoramic image you want. I found a few free images here: https://pixexid.com. Add any new images to your static_assets folder because that is where React 360 will look for all of your static assets like images, sounds, and models. You can update the environment background in the client.js file like this.

r360.compositor.setBackground(r360.getAssetURL('simmes-start-screen.jpg'));

The asset URL used to be 360_world.jpg and now it's been updated to be the start screen of a VR app I'm working on. One thing I was a little disappointed in was the lack of built in primative shapes. You can't just build objects to place in your world natively. You have to build models outside of the app and import them. There are some free resources out there, but they aren't the best. So be aware that you can't build boxes and spheres in React 360.

Add some interactions with the app

The fun part of any VR app is interacting with it. You can do that with the use of the VrButton component. We'll add it to the imports in the index.js file like this.

import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  VrButton
} from 'react-360';

We'll make a simple counter to keep track of how many times a user clicks a button. To do that, we'll need to add a little extra functionality. First we'll set the initial state of the component and set the count to 0.

state = {
  count: 0
};

Then we'll make a function to increment that count like this.

_incrementCount = () => {
  this.setState({
    count: this.state.count + 1
  })
}

Lastly, we need to add the VrButton to the render method.

<View style={styles.panel}>
        <VrButton
          onClick={this._incrementCount}
          style={styles.greetingBox}>
          <Text style={styles.greeting}>
            {`You have visited Simmes ${this.state.count} times`}
          </Text>
        </VrButton>
</View>

Notice that we have an onClick event for the VrButton that calls the _incrementCount function. That's how we handle the user input. Then we have given the button the same styles that were on the View that held the Text before our change. Another change you'll notice is that we have updated the text inside of the Text component to a template string. We're returning the number of clicks a user has made and letting them know that's how many times they have visited the Simmes VR world.

Add sound to the app

Not every VR app will need sound, but for things like games or completely immersive worlds you might want to include it. To add sound to this project, we'll need to import a few more things from React 360 in the index.js file.

import {
  asset,
  AppRegistry,
  NativeModules,
  StyleSheet,
  Text,
  View,
  VrButton
} from 'react-360';

Next we need to get the AudioModule from the NativeModules and we'll do that by creating a new const.

const { AudioModule } = NativeModules;

The audio functionality we're going to implement will play some sound when a user clicks a button and stop playing it if a user clicks the same button again. To handle that, we'll add a Boolean value to the state.

state = {
  count: 0,
  playSound: false
};

Then we can add another function that will handle how sound is played.

_playSound = () => {
    this.setState({
      playSound: !this.state.playSound
    });

    if (this.state.playSound) {
      AudioModule.createAudio('sza', {
        source: asset('brokenclocks.mp3'),
        volume: 0.5
      });

      AudioModule.play('sza');
    }
    else {
      AudioModule.stop('sza');
    }
  }

When this function is triggered, the first thing it does is update the playSound state which is initially false. Depending on the value of playSound you'll either start playing your sound or stop it. If you need to start playing sound, then you can create an audio instance to work with. The createAudio method takes a name and any options you want to pass in. You need to pass a source file at the minimum. That's why we imported asset from React 360. It lets us get files from the static_assets folder easily.

Once your audio instance is created, you can play it by referencing the name you assigned to it. That's what happens when playSound is true. When it's false, you'll stop the sound and that gets rid of the audio instance. That's why we make a new one each time playSound is true.

Lastly, we'll add a button that will play or stop the sound.

<View style={styles.panel}>
 <VrButton
    onClick={this._incrementCount}
    style={styles.greetingBox}>
    <Text style={styles.greeting}>
     {`You have visited Simmes ${this.state.count} times`}
  </Text>
 </VrButton>
 <VrButton
   onClick={this._playSound}
   style={styles.greetingBox}>
   <Text style={styles.greeting}>
     {'You can play the music of your people'}
   </Text>
  </VrButton>
</View>

It's just another VrButton, but this time the onClick listener calls the _playSound method. Otherwise this is almost identical to the other VrButton. You could get a little fancy and change the text that's shown in the play/stop button based on the value of playSound. Now that you've added this sound functionality, we're done with this simple app! It's time to build it.

Run the app and play with it

Run npm start to see what your new app looks like. It'll probably look different from what I have, but here's a shot of mine.

https://cdn-images-1.medium.com/max/800/1*FvvzZCrQ5aQj7f1q12o9Vw.png

You have some kind of background and two buttons, one of which is a counter and the other is an audio control. Now you can play around with your new world and start thinking of things you want to add to it. You could make a crazy VR game or you could make something to help people with accessibility. There are a lot of things you can build off of this project with a little creativity and imagination.

Hopefully this gave you a good starting point for working with React 360. It's a cool library to use to get into VR development. You don't need to invest in an expensive headset to test your apps. You can do it right there in the browser. Don't expect to see much in the DevTools though because it's all rendered in a canvas. There aren't individual elements like you might expect.

Do you think VR will be worth learning how to develop or will it be a fad? It would be cool if there was an AR library for the web, but how would that even work? These are new fields and they are wide open right now. Since you know what technical skills you'll need, try focusing on the creative side of what you can build with a VR application.


Hey! You should follow me on Twitter because reasons: https://twitter.com/FlippedCoding

Discussion

pic
Editor guide
Collapse
yuliia07129578 profile image
Yuliia

I wanna thank Milecia McG for such a helpful article, I was curious of how to develop VR app with React360, so I start investigating this topic throughout the web, and I found this blog litslink.com/blog/a-complete-guide..., where you can learn how to create a VR app step by step, never thought that it’s not so complicated

Collapse
rumman92 profile image
Rumman Siddiqui

I tried this but unfortunately I am not able to get past the first step, end up getting: -bash: react-360: command not found when I do react-360 init ProjectName.
Can you help, added question here as well: stackoverflow.com/questions/586570...

Collapse
ben profile image
Collapse
darryldexter profile image
Darryl D.

This looks awesome! Does it have any support for the Oculus quest? As in being able to walk around a space.

Collapse
flippedcoding profile image
Milecia McG Author

I'm not sure if it supports Oculus quest, but I've used it with some of the smart phone gear.

Collapse
willjohnsonio profile image
Will Johnson

This is a really good post!

Collapse
wakeupmh profile image