Virtual Reality Game Development with Oculus API: VR Ninja
This project was carried out throughout the entire semester as teamwork for the CS-444 Virtual Reality module at EPFL. We were asked to make a VR game with Oculus API in Unity which includes certain interactions with the virtual environment and locomotions. We thought the best way to achieve these requirements would be a Ninja game where players can fight enemies and solve puzzles with different skills. This blog will describe details of gameplay and all stages of game development, from level design to implementation and testing. I was in charge of the code implementation part of this project. Without further ado, let’s get started.
Synopsis
In this game, the player acts as a ninja whose job is to help the young emperor defeat the evil shogun. The player must learn basic combat systems, including close-range (sword) and mid-range (ninja star). Furthermore, the player needs to solve puzzles that use additional mechanics such as potion-making, spirit grabbing, and teleportation to advance through stages.
Scenarios & Interactions
There are four stages that a player must go through in order to complete the game. Each of them will be described below.
Tutorial
The player first enters the tutorial level, where they learn all the game mechanics: combat, teleportation, spirit grabbing, and potion-making. Each mechanic is introduced by a character in the game. A detailed list of what the player can do is shown below:
Move around in the world by using the left joystick. This action is intuitive, and hence there is no tutorial for it.
Unsheathe the sword by pressing the A or X button and then swinging it around. This will allow the player to deal damage to enemies at close range. Swinging faster and harder deals more damage.
Take out a ninja star with the B or Y button and then release it to throw it at enemies. This way, the player can fight enemies at long range.
Crouch and hide behind objects in the scene to avoid enemies. This is done by crouching in real life.
Teleport to different locations by holding the right index trigger and drawing the appropriate symbol (circle, star, or right arrow) with the controller. Different places are associated with different symbols, where drawing the symbol takes the player to that specific location.
Grab objects at a distance by first sending out a Grabber Spirit onto the object you want to grab with the left index trigger. The player can control where the Grabber Spirit goes by aiming at the left controller. Once the Grabber Spirit has reached the desired object, it gets highlighted in red, and then he can pull the object towards him with the right or left-hand trigger.
Make potions (Filling a Container) by adding all the ingredients into a cauldron with the Spirit Grab, then putting the potion vial with the spirit Grab into the cauldron to fill it up.
Look at your remaining health by looking at the virtual left hand. It has five petals initially, and each time the player takes damage from an enemy, a petal will fall off. If all petals fall off, he dies.
Passing through Enemy Village
After finishing the tutorial, the player will be teleported to the entrance of a dangerous village with enemies patrolling. The player has to find their way to pass through the village. Typically, the player goes through the following loops at this level:
Core Loop: The player has to analyse their surroundings to determine a plan of escape from the guards. Depending on the player's performance, they either get caught or sneak around. Thus, the player enters a 3-stage loop where they have to plan their route, then execute it in a second step, and a final stage where they recover in a new hiding spot to analyse the new environment.
Smaller Loop: The smaller loop consists of running, crouching, or fighting enemies.
Opening the Gate
When the player finds their way through the village and reaches the gate, he needs to unlock the gate to the final boss fight. In order to do so, the player has to brew a potion with three ingredients that can melt the magical seal on the gate. This is a puzzle where the player needs to figure out where the ingredients are and how to reach them. There are clear indications of the locations of the ingredients, which help the user solve the puzzle.
Cheat
There is only one cheat in the game: the method to unlock the magically sealed gate. The player does not have to put all the ingredients into the cauldron. Instead, they can throw one ingredient on the door, which will advance them to the boss fight.
Boss Fight
The final boss fight is triggered once the player enters the gate. There are three flags in the scene, indicating three teleportation sites. The player needs to figure out how to defeat the boss with the weapons at hand and the teleportation skill. The boss's health, speed, and attack are carefully tuned so that the boss is not too difficult to beat while still guiding the user to come up with different combat strategies.
Design & Implementation
The class diagram of the game is shown below.
The dotted line means a class inherits from the start of the
arrow, while a black line means a class uses the start of the
arrow. There are seven major systems implemented:
Weapon, Enemy, Spirit Grab, Teleportation, Potion, Audio,
and Other. There is no implementation for the basic user
movement (NavMeshAgent
) and the animation
(ThirdPersonCharacter
) because those two are
included in the Unity API.
It is worth mentioning the most difficult features to
implement, which are the movement recognition for
teleportation and scripting on top of Unity's provided
AI library. The movement recognition was done by
periodically checking the user's controller movement
when they press the index trigger. After that, the list
of positions was fed into a recognition algorithm that
would return the predicted shape. Using the
(NavMeshAgent
) and the
(ThirdPersonCharacter
) provided by
Unity to control AI was a significant challenge for me.
By calling these two functions inside
(BasicController
), I was able to program
the AI to wander in the beginning and then start
attacking the player when they are detected by the
(AISensor
) script. Therefore, I had to
spend much time reading the code of these provided
scripts to understand unwanted behaviours when bugs
appeared.
Playtesting
The table below shows the feedback that we obtained from our five playtesters. We encouraged playtesters to give us feedback while playing and did not communicate with them during playtime. The only exception is that since parts of our tutorial were unclear, we had to give them some oral explanations. At the end of the session, we would ask them if they had any additional feedback and tell us what they liked and did not like about the game. The table also shows what changes we implemented to address our feedback from playtesters.
Special Care
Cybersickness
Special care was given to the quality of the game's graphics to maximise immersion. We used a low-poly asset pack which fit the game's theme so that both the style and performance were maintained. We also decreased the sampling rate of the graphic to prevent aliasing, which reduced the jaggedness of the graphics. This was one way of reducing cybersickness. Furthermore, we considered the feedback from testers about cybersickness and tried to make sure the movements in the gameplay corresponded to real-life actions. With that said, we disabled the possibility of looking around using a joystick, and we decided that the player has to crouch in real life to hide from enemies instead of just pressing a button. We also kept the number of hills to climb in the game low since vertical movement can trigger cybersickness. It was also decided that we would not include the grappling hook mechanic since that could be a source of cybersickness. We made teleportation conserve player orientations so that they will not be disoriented.
Sound Effects
We paid attention to the sound effects and background music. The sound effects are triggered when specific actions are taken by the player, such as brewing a potion or teleporting. This provides audio feedback to the player and improves the user experience. All pieces of background music are selected to have a Japanese style. Moreover, the emotions of the music vary according to the level of the game. For example, the music of the tutorial level is cheerful, while that of the boss fight is intense. This contributes to immersing the player and making the experience more enjoyable.
Difficulty
We took our inspirations from the Dark Souls series, where the player needs to assume the world is a dangerous place and it needs to be explored with high caution. VR Ninja is designed so that the player needs to think about different tactics to advance through the levels. We encouraged this aspect by making the enemies sensitive to detect the player and hard to kill.
Download the Source Code
Click the button to download the source code!
Acknowledgements
I want to thank the students who gave us honest feedback on the game, StackOverflow, and the TAs who answered our questions on Discord. I would also like to thank my teammates for their dedication to this project.
Other Work on this Module
For this module, I also did a paper study on To Stylize or Not to Stylize? The Effect of Shape and Material Stylization on the Perception of Computer-Generated Faces. If you are interested, click the button below.