Building Your First VR Game

Nicolas Gatien
7 min readMay 27, 2021

--

Hello!!! 👋 After developing 2D games for 2 years, I finally decided to add a 3rd dimension. And instead of making a simple 3D game, I decided I should make a VR Game! This was a great idea…

Nonetheless, here's how I made my first VR Game using the Unity Game Engine! In tutorial form, so you can follow along! 😄

PS: (This article assumes you have basic Unity 3D knowledge)
PPS: (
Here is the finished game we are building)

By @nampoh on Unsplash.com

🔌 Project Setup 🔌

After creating a new 3D Unity project, your gonna want to head over to the Unity Asset Store and find the Oculus Integration package. Click the blue “Add to My Assets” button on the right, and head back over to your unity project.

Back in Unity, open the package manager window and select: “My Assets” in the drop-down menu.

The Oculus Integration package should now be visible.

If you navigate over to the Oculus Integration in the top left of the Package Manager and select it. You can import it into your project by pressing the “Import” button in the bottom right corner of the window.

Once it is imported, search in the project tab for “OVRCameraRig” and drag it into the hierarchy and reset its position to (0, 0, 0). The Oculus Integration automatically handles all the position and rotation calculations between the real headset and the virtual camera rig. Your project is now set up and we are ready to go!

🎮 Game Scripting 🎮

Adding Swords 🔪

first step is finding sword models to add to your game! I found these weapon models itch.io for free, but you can find yours anywhere, as long as the models are in OBJ format.

Import your sword models into Unity, and add each sword under their corresponding hand anchors under the OVRCameraRig game object.

Give both of these swords a Mesh Collider and check off Convex and Is Trigger as options. This will allow collision detection further on!

Create a new tag for your swords called “Sword” and add it to each one.

The final step is to add a new script named: Sword to both your swords. The Sword script will handle playing a sound whenever we slice a cube.

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Sword : MonoBehaviour{public AudioSource sliceAudio;public void PlaySliceSound(){sliceAudio.pitch = Random.Range(0.7f, 1.5f); // randomize pitchsliceAudio.Play(); // play sound}}

After the script is added, add an AudioSource component to the swords, and drag in any audio clip. The clip will be played every time a cube is sliced.

Score Management 🏅

Create a new UI>Text-TextMeshPro in the Hierarchy, and import the TMPro essentials package from the pop-up.

Select your newly created text, and create a new script called: “Score Manager”

using System.Collections;using System.Collections.Generic;using UnityEngine;using TMPro;public class ScoreManager : MonoBehaviour{public TextMeshProUGUI scoreText; // reference to selfpublic static int score; // static to make it easy to access accross all scripts & scenesvoid Start(){scoreText = GetComponent<TextMeshProUGUI>(); // self referencescore = 0; // reset score}void Update(){scoreText.text = "Score: " + score; // update score display every frame}}

Select the newly created Canvas, and change the render mode from “Screen Space - Overlay” to “World Space”. Move it to a new position in front of the player to make it easier to read.

Death Platform 💀

Create a new 3D Object>Plane and a new tag called “Die”. Tag your new plane with Die, check Convex & Is Trigger on the Mesh Collider and add a Rigidbody component with Is Kinematic checked.

This platform will destroy any cubes that come in contact with it, so reset its position, and move it down to -3 on the y axis.

Sliceable Cubes 🧊

Create a new 3D cube object in the Hierarchy, and drag it into the project view to create a new prefab. Add a Rigidbody component to it, and create a new script called “Shape”

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.SceneManagement;public class Shape : MonoBehaviour{public bool sliced; // used to see if the object has been cut at allpublic bool cut; // used to make sure if you hit the same shape with 2 swords at the same time, it doesn't summon double the amount of shapespublic int score = 5; // base score at a full sizepublic float size = 1; // base start sizepublic float sizeDivider = 2; // how much should the size of the shape be divided by every time a player slices itpublic int scoreMultiplier = 2; // how many more points should a player get for slicing smaller cubesvoid Start(){GetComponent<Rigidbody>().mass = size; // assign objects mass equal to it's sizecut = false;}// Update is called once per framevoid Update(){transform.localScale = new Vector3(size, size, size); // reset sizeif(size < 0.125f) // destroy the game object if it gets too small to slice{MinSizeReached();}}private void OnTriggerEnter(Collider other){if (other.CompareTag("Sword")) // check if we collide with an object with a sword tag{if(cut == false) // check if it's been cut before? This stops it from summoning more shapes than it should{other.GetComponent<Sword>().PlaySliceSound(); // play the sound from the sword scriptSliced();}cut = true;}else if(other.CompareTag("Die")) // check if we collide with an object with a die tag{if(sliced == true) // if the cube has been cut at all, then nothing happens and we can just destroy the cube{MinSizeReached();}else // if not, the player has missed a cube, and must restart the level{SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);}}}void Sliced(){sliced = true;ScoreManager.score += score; // add scoreGameObject offcut1 = Instantiate(this.gameObject, transform.position, Quaternion.identity); // create smaller versionsSetOffcutVariables(offcut1); // set variablesGameObject offcut2 = Instantiate(this.gameObject, transform.position, Quaternion.identity); // repeatSetOffcutVariables(offcut2);Destroy(this.gameObject);}void SetOffcutVariables(GameObject offcut) // apply all the multipliers{offcut.GetComponent<Shape>().size = size / sizeDivider;offcut.GetComponent<Shape>().score *= scoreMultiplier;offcut.GetComponent<Rigidbody>().velocity = new Vector3(Random.Range(-1, 1 + 1), Random.Range(3, 7 + 1), Random.Range(-1, 1 + 1)); // makes the offcuts go in a slightly random directionoffcut.GetComponent<Shape>().sliced = true;}void MinSizeReached()Destroy(this.gameObject);}}

Shape Spawner 💾

Create a new Empty GameObject and set its location right above the death platform. Create a new script called “Spawner”

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Spawner : MonoBehaviour{public GameObject[] shapes; // list of shapes the spawner can spawnpublic float startTimeBtwSpawns = 3;float timeBtwSpawns; // current time before another shape[Header("Start Velocities")]public float XminStartVelocity = -0.2f;public float XmaxStartVelocity = 0.2f;[Space]public float YminStartVelocity = 7;public float YmaxStartVelocity = 10;[Space]public float ZminStartVelocity = -0.2f;public float ZmaxStartVelocity = -2;private void Start(){timeBtwSpawns = startTimeBtwSpawns; // reset time at start}void Update(){timeBtwSpawns -= Time.deltaTime; // remove time from timerif(timeBtwSpawns <= 0){timeBtwSpawns = startTimeBtwSpawns;SummonObject();}}void SummonObject(){startTimeBtwSpawns *= 0.99f; // shorten time btw spawns to make game harder over timeGameObject curOBJ = Instantiate(shapes[Random.Range(0, shapes.Length)], transform.position, Quaternion.identity); // summon objectcurOBJ.GetComponent<Rigidbody>().velocity = new Vector3(Random.Range(XminStartVelocity, XmaxStartVelocity+1), Random.Range(YminStartVelocity, YmaxStartVelocity+1), Random.Range(ZminStartVelocity, ZmaxStartVelocity+1)); // make it go in a random direction}}

Environment 🌲

You can download forest environment models off of itch.io or the unity asset store to build a nicer-looking environment. As a bare minimum, I recommend creating a new 3D Object>Plane above the spawner as a barrier between the player and the appearing cubes. This will make it look as if the cubes are passing right through the ground.

🧱 Building Your Game 🧱

Open your build settings under File>Build Setting and switch to an android build. Plugin your headset to your computer through a USB cable, and with developer mode enabled on the headset (check out this article if developer mode isn’t enabled), press build and run, and play your game! You’re done! Good job!

Hopefully, this article helped you build your first VR Game! 🎉 If you have any questions or feedback for this article, please contact me by commenting on this article! See you soon with another project! 👋

Hey! If you enjoy reading this article, consider clicking that 👏 50 times. If you want to read my articles as soon as they are published, subscribe to my Medium account. And if you want to stay updated with what I’m up to, here is my Newsletter. See you soon!👋

--

--

Nicolas Gatien

Hi! I'm Nicolas! A 17-year-old game designer & maker. I build things and write about them!