Aaron Petrek
Game Developer
Project Specifications
-
Multiplayer game for VR location-based arcade
-
Developed in Unity 2020, OpenXR, Mirror Networking
-
Competitive VR ESport
Project Goals
-
Gain experience developing VR multiplayer gameplay mechanics
Summary
Competitive VR E-Sport for location-based VR arcade. Players control paddles in VR to hit a ball and try to score goals on their opponent. Players can influence the ball’s movement as they apply spin to the ball using their paddles. This game is built in Unity and uses the OpenXR API.
Itch.io Page
Game Summary
Challenge your family and friends to an intense futuristic competition! Engage in thrilling 1v1 matches where skill, hand eye coordination and physical stamina are your ultimate assets. To win, outscore your opponent by strategically maneuvering a high-speed ball past your opponent.
Equipped with two hologram paddles, players dive into heart-pounding showdowns. Use these paddles not just to defend your goal, but also to masterfully apply spin to the ball, crafting dynamic trajectories that challenge your rival's reflexes.
Every match becomes a duel of wits and agility, where split-second decisions and calculated moves determine the difference between victory and defeat.
Game
Curveball is a competitive 1v1 VR ESport. Players compete against each other by trying to score more goals than their opponent. Each player has a pair of hologram paddles they use to defend their goal and manipulate the ball's movement. Players can apply spin to the ball, creating a magnus effect that will result in the ball altering its trajectory as it heads toward their opponent's goal.
Player VR Experience
Because Curveball was developed for a VR arcade, there were several design factors that had to be considered for customers. As with previous projects seen at a location-based VR center, this experience would be many individuals' first experience with not only VR gaming but also their first time using any VR device. Because of this and the fact that customers would be paying to play the game on an hourly basis, I wanted the user experience to be as smooth as possible and get the players actually playing the game quickly. While playing Curveball, the user does not need to press any buttons on the motion controllers. Using an IK plugin, the players see their hands in VR by extending their index finger. The movement is shown in VR. I found this to be a very intuitive approach for players inexperienced with VR as they simply press the buttons on their hologram menu to navigate through courts and setup between rounds.
Steps 2 through 5 are repeated until one player does not register a collision. At this point the ball will go past the missed player's hologram paddles and a goal will be scored resulting in a point for the other player. Once a goal is scored the round has ended and the process above will restart from Step 1.
Player 1 hits the ball locally. The collision is computed locally along with the reflection angles and paddle velocity used to determine the ball's curve trajectory through the air along with the ball's axis and speed of spin. This collision makes up a new collision state. The new collision state is sent to the server for verification and correction if necessary. The server will then forward this new state to Player 2.
At the start of a round the ball is served and starts moving toward the player who was scored upon last, in this case player Player 1. An RPC from the server tells both players to start moving the ball toward Player 1. Due to different arrival times of the RPC, the exact movement start time of the ball, and therefore its subsequent updated location will not be exact for each player.
Player 1 continues to move the ball after the collision according to its locally calculated collision state, assuming no server correction was needed. Player 2 will move the ball according to the collision state received from the server. Because of the latency of sending the collision state to Player 2, the ball location will lag behind the position seen by Player 1. Player 2 will send updates of the ball's location and timestamps to Player 1 via the server. Player 1 will verify or correct this past position using saved location states between updates from Player 2.
Player 2 hits the ball locally. The collision is computed locally along with the reflection angles and paddle velocity used to determine the ball's curve trajectory through the air along with the ball's axis and speed of spin. This collision makes up a new collision state. The new collision state is sent to the server for verification and correction if necessary. The server will then forward this new state to Player 1.
Player 2 continues to move the ball after the collision according to its locally calculated collision state, assuming no server correction was needed. Player 1 will move the ball according to the collision state received from the server. Because of the latency of sending the collision state to Player 1, the ball location will lag behind the position seen by Player 2. Player 1 will send updates of the ball's location and timestamps to Player 2 via the server. Player 2 will verify or correct this past position using saved location states between updates from Player 1.
Ball Movement
From the start of development, this game was intended to be played at a location-based VR arcade, and therefore has the advantage of playing over a wireless LAN connection. However, due to the fast movement required for the ball and to keep the competitive feel of the game, lag compensation was still required. I developed a prediction algorithm for the ball movement. This hides the latency and visual discrepancies when the ball changes direction from a collision with the player's paddles. Collisions and resulting ball reflections are computed locally on the player's device and then verified on the server.
The example below shows a possible state of this architecture. Player 1 and Player 2 are both in the Player Staging area. Each player will have the Player Staging Environment scene loaded which contains all the visuals for the level. Each player will also load the Player Staging scene. This scene is also loaded on the server and handles all gameplay functionality such as updating various gameplay states the environment scene will use. The Player Staging scene also handles the RPCs and replicated variables for VR Player client interaction with the server.
The setup in court 1 is similar to that of the Player Staging area in this example. In addition to Players 3 and 4 in the court, there is also a Spectator watching the match. As with the Player Staging scene, the Court 1 scene will facilitate the match and is loaded on the server and all three clients. Each client, both VR players and the Spectator will also load the non-networked court environment scene.
After learning about additive scenes in Unity and how to isolate Unity GameObjects in one scene from another using Mirror Networking, I determined this would be my best approach to get the behavior I wanted where four courts could run from a single headless server.
Each Court and Player Staging area is made up of two scenes. One for the gameplay, and the other for all the visuals. The server always has each gameplay scene loaded simultaneously. The VR Players and Spectators then load a single gameplay scene corresponding to their current court or player staging area along with the environment scene for all the visuals.
Server
The headless server hosts 4 courts simultaneously where players can play against each other. It also hosts a single player staging area that allows players to practice and travel to the courts. Each court and staging area runs independently while communicating with a single Curveball Online Manager.
Spectators
Standalone PC and mobile versions of Curveball allow for viewing the VR players in both a third and first person perspective. These spectators are unknown to VR Players in each court and may join and leave multiple times during a match.
VR Players
Players wear VR headsets. These are the actual players playing the game and competing against each other.
Scene Architecture
One of the first major obstacles when building Curveball was deciding how to architect this game for a location-based environment. Originally I had an individual server to facilitate each match between two players. Realizing this would not scale well, and potentially result in bad user experience moving between servers, I looked for a way to host everything from a single headless server. I identified there would be three different instances of the game running simultaneously to make up the client-server architecture of Curveball.
Development
Curveball is the most complex solo project I have worked on. Creating this game for a location-based VR entertainment, and achieving a competitive VR ESports feel, offered me many obstacles and learning opportunities.
For this game jam there were a total of 984 entries. Unfortunately they results did not go in our favor. In players reviews there was a consistent issue with the enemy AI being too accurate. This was unfortunate because the enemy AI system I designed and programmed allowed for the enemy accuracy to change dynamically. If given more time and having other play test the game this issue could have easily been corrected. I feel the game as a whole suffered from this issue.
Reception
Project Reflection
If I were to redo this project I would have done things differently. Given the fact I was working in a low latency environment and due to the nature of the gameplay where the ball’s movement state is recomputed regularly as a result of the collision, I was able to use Unity’s built-in physics engine. If I were to extend this project and add playability outside of a LAN environment, I would use kinematics to move the ball according to my own calculated forces. When starting this project, using a kinematic movement approach was beyond my capabilities. Looking back now I feel confident I would be able to implement this approach.