My project is a videogame that integrates augmented reality. The game is a survival shooter that is played with mouse and keyboard. The goal of the player is to survive as long as possible and improve his own best score every time.
The gameplay is divided in two phases that alternate until the player dies. The first one is the wave phase, which is when the enemies spawn and the player needs to kiil them all. Once he does it, the game goes to the next phase: the placing phase. Here the player has a limited amount of time to place some objects and traps that will help him in the next round. Killing monsters grants the player points that contribute to the general score and allow him to buy said objects.
During the wave phase the player is free to move inside the arena and shoot the enemies down. As the game goes on, the amount of enemies per round, the maximum number of enemies that can be spawned at once and the spawn timers will change, increasing the difficulty of the game. Every 4 waves, the game will spawn a miniboss that deals a lot of damage and has a lot of HPs. Killing it will also grant many more points than the usual enemies. There is no time limit for the wave phase, the only possible outcomes are: the player dies, ending the game, or the player successfully kills all the enemies and starts the placing phase.
The arena is tracked with an image target, so the player can position the webcam in different places and can choose his preferred perspective. The game is developed in such a way that the direction of movement of the character is decided based on the position of the camera. This means that the "go north" button will always move the player to the current north, depending on where the webcam is placed. In any moment, during the game, losing track of the arena target pauses the game. This is really useful to avoid situations where the target is lost but the game is still running, resulting in an eventual death of the player or at least a loss of gameplay time, which in turn would annoy the user.
The placing phase uses the AR capabilities more extensively than the wave phase. Each object is associated to an image target. The player will be able to place the objects on the arena thanks to these targets and the press a button to confirm the placement. The user can place more than one object at the time, but he needs to care about the price of such objects. Each of them needs to be bought using the points accumulated in the past wave phases. Spending points doesn't decrement the score, which is separated by the currency model.
If the player makes a mistake or is unsatisfied about a placement he can press a button to undo the last purchase. All of the placements of the current phase can be undone and the points used to buy such objects are returned.
Here's a list of the five different objects:
Mud zone: a small zone that slows all the enemies that enter it.
Lava zone: a small zone that damages all the enemies that enter it.
Invulnerability buff: a cube that, if picked up during the wave phase, makes the player invulnerable to damage. Only lasts for a couple of seconds.
Damage buff: a cube that, if picked up during the wave phase, doubles the player's damage. Only lasts for a couple of seconds. Different damage bonuses can be stacked and the duration is refreshed with each pick up.
Healthpack: a cube that, if picked up during the wave phase, heals the player.
The arena has four different spawn points. There are three types of enemies, all of which have slightly different movement speeds and deal different amounts of damage to the player. Each of them has one attack that is triggered when the player is close enough to them. Also, each kind of enemy gives a different amount of points and has a different number of hit points.
This is the list:
Skeleton warrior: this is the least troublesome enemy of the three. It has the lowest health and deals the lowest damage. However its speed is the same as the player, which makes it a real threat. The attack animation is rather long and the player can easily avoid it.
Green monster: the monster is an upgraded version of the skeleton. It's bigger, has more health and deals more damage. It's also quite slower, but its attack animation is pretty fast, so the player will need to move quickly in order to avoid the damage.
Rock monster: this is the miniboss of the game. It's a huge magical monster made of rocks and it spawns once every four waves. It deals an insane amount of damage, so the player better prepare by healing up and placing a couple of healthpacks before the round. This monster is also REALLY slow, so getting around it is rather easy. The problem is when there are plenty of minor enemies around it during the later waves of the game.
It's possible to pause the game whenever you want. There are no particular options in the pause menu, but it's useful to take a break. Also, as I already wrote, the game will be paused automatically if the game loses track of the arena. It's only possible to unpause if the arena is tracked.
The UI is rather simple. These are the components:
Healthbar: a bar that shows the player's remaining hit points.
Score counter: current score achieved so far.
Point counter: number of points available for object purchase during the placing phase.
Phase indicator: shows which is the current phase.
Timer: shows either the total time spent playing during the wave phases or the countdown timer of the placing phase.
The game keeps track of the top score in a file located in the Resources folder. When the player dies, the current score is compared with the top one and the top score is updated and saved if the player surpassed it. When the player dies he can press a button to restart the game.
Assets and Credits
This is a list of all the assets that have been used for the project, including the credits for each of them. Click on the images to go to the website.
I've been able to implement everything I planned to have in my game. During the development I've encountered some problems and difficulties, here are some of them:
Implementing the movement has been a real challenge. At the start of the project I didn't know that it was possible to fix the center of the world to one of the targets, instead I had the camera fixed at the center. This meant that in Unity the arena was moving around and that would've made my life hard when implementing gravity, movement and hit detection. The real challenge of the movement system was to adapt it so that the player would move "up" if he wanted to, instead of moving to the fixed north of the arena. This problem was due to the fact that the player can place the camera wherever he wants, which means that the arena could be seen from any point around it. I tried to use some math and Quaternions to rotate the movement vector based on the position of the arena, but after days of prototyping the results weren't so great. In the end, as I said, I discovered that I could just fix the center of the world with the center of the arena target, which made my life much easier. Now the arena would've stopped moving around and I could just project the rotation of the camera on the plane corresponding to the floor of the stage to find the correct rotation to apply to the movement. Having a fixed arena also allowed me to easily implement other things such as hit detection of the bullets and pathing of the enemies.
I decided to synchronize all of the game logic using a class called GameLogic. Implementing correctly the various functionalities such as enemy spawn and alternation of the phases wasn't hard per se, but it required a lot of work.
Implementing the enemies was quite hard at first because of my inexperience with animators and trigger interaction, but in the end I've been able to develop a series of scripts that could be easily added to any kind of enemy. At that point it was just a matter of setting the parameters correctly, setting up the NavMeshAgent (which is a simple AI provided by Unity) and creating the right colliders for hit detection and player detection.
The next big challenge has been implementing the targets for the objects. I initially tried to use some simple cards, like the ones used to play poker. The tracking wasn't really working though, the objects would appear above the arena even if the cards were lying on the image target. In order to fix this problem I used the magazines targets from project 1, cut in four pieces each. These images had way better targeting and they also were small enough to keep the arena visible during the placement of the objects. Even if the situation was improved, the objects would still spawn a bit above the arena and they also kept the rotation of the target. So I developed a script that rotates them to keep the rotation about the y axis, but effectively aliminating the ones about the x and z axis, guaranteeing that the object would be lying correctly on the arena. Also, the y coordinate at which they spawn is fixed, so if you keep the target above the arena, the respective object will always spawn right on top of the stage.
Another small challenge was to reset the game after the player dies. I tried reloading the scene but it would screw the textures over. So I had to manually keep track of the enemies still alive, destroy them and initialize the game scripts and player scripts back to their original state.
I wanted the rounds to get progressively harder, without using a linear function though as that would've created many problems during the later rounds, such as way too many enemies to kill, really low respawn timers and too many enemies that could be on screen at the same time. Therefore I used a series of functions with horizontal asyntote, which means functions that would tend to a finite number when the parameter tends to infinity. This way the game keeps getting more challenging, but after a while the waves will change only a bit. The main increase of difficulty is right in the first rounds.
When I started this project I had in mind to implement some objects that would serve as obstacles, like walls or boxes. The NavMeshAgent though bases its AI on a baked space, which means that the walkable space for the enemies was decided even before compile time. This and the fact that I started thinking that having additional obstacles would be a bad idea brought to the decision of simply not implementing them.
How to run and download links
You can download the unity project folder from the following link. All you have to do is load it in Unity and run the scene, make sure to install the Vuforia extension in case something doesn't work. I used Unity 2018.2.13 to develop and run the project. The images used as targets are also listed here for printing. Download link
In order to play you need to cut the magazine targets in the following way: (4 pieces of magazine 2 and top-left piece of magazine 1)