top of page
Albacora: VR Submarine Piloting Game

Albacora is a VR submarine piloting game that I am working on with a team. You move the sub around by interacting with different interactable controls in the submarine. For this project, I am working on the movement of the submarine, and the fish flocking.

The submarine mostly uses jerk-based physics in order to move around. The levers control the jerk value of the submarine as well as the maximum velocity of the submarine. The jerk value is then added to the acceleration which is then added to the velocity. I chose to use jerk-based physics because my goal is to make smooth and intuitive movement. I found that this was not the best solution for some of the aspects of the submarine movement.

​

One design decision that was made early on in the project was to restrict the pitch rotation of the submarine. The reason for this is to make it so that it is a bit easier for the player to orient themselves in the game world, as well as helping prevent motion sickness. Restricting the pitch rotation conflicted with using forces. I found that using forces made the behavior of the pitch cap much harder to predict. I decided to try a different approach, which used a smooth lerp instead of forces. I found that the smooth lerp did exactly what I wanted out of the pitch cap, and it does it with significantly less code, so I decided to switch to that for the pitch rotation.

​

I initially made the submarine rely on rigidbody physics to move and collide with other objects. It quickly became clear that this was not the best approach due to issues with objects flying inside the submarine and adding unpredictable forces to it. To solve this issue, I switched all of the movement logic to be kinematic. Through this experience, I learned that rigidbody physics aren't necessarily always the best way to solve a problem.

​

Switching the submarine to kinematic introduced a new problem where collision resolutions didn't occur. To fix this problem, I added a script to the front, back, top, and bottom colliders of the sub that add to collision counters whenever a collision occurs. When the front collision counter is any value but 0, the submarine can no longer move forward. The backward, top, and bottom checks work the same way.

​

For those who potentially struggle a lot with motion sickness in VR, I created a constant velocity mode option for the movement of the submarine. Through testing the game, I found that the constant velocity mode is a lot more fun than I initially thought it was going to be. This is because the core of the experience of moving the levers in VR is still in tact. Additionally, I aided in positioning the levers in the submarine to find the most comfortable layout.

​

I created a Flocking Agent that holds the fish flocking logic and a Flocking Manager which holds all of the flock settings of the entire group. The flock has flock avoidance, obstacle avoidance, alignment, cohesion, and different bounds conditions that can be used to customize the behavior of the flock. There are inner and outer bounds conditions for either a spherical mode or a cylindrical mode.

​

To make the flocking logic more efficient, I moved it into a class that inherits from the IJobParallelFor interface from the Unity Job's system. In order to continue to do raycasts for the obstacle avoidance logic, I moved the calculations out of the job class so that they could be done in the main thread. Given the target of 90 fps for VR games, I found that the updated logic supported around 300 fish to be on screen at one time if they aren't clumped together. I found that using Unity's occlusion library, many more fish can exist offscreen without heavily impacting the performance.

​

I am using behavior trees to control when the fish flock does certain special behaviors. For example, using a behavior tree to make the fish follow a path. In the start function of the Follow Path node, I set the values of the Flocking Manager, which then immediately adjusts the behavior of the fish flock to whatever is needed. In the update function of the Follow Path node, I increase a t value and evaluate it’s position on a path. I then set the position of the Flocking Manager to the position on the path. Due to the bounds conditions, the fish are motivated to follow the Flocking Manager.

bottom of page