INTERSTELLAR RACING LEAGUE (IRL)
IRL is a couch co-op multiplayer racing game set in a futuristic world. Vehicles can be enhanced by boost, knock and shield power-ups. Players have the option to choose between Sprint, Grand Prix, and Time Trial game modes.
Role & Responsibilities
Physics Team: I worked on the Physics team for the majority of the project We were responsible for the physics on the vehicles, the camera system, collisions, and track features like power ups.
Race Logic Strike Team: In a later stage of the project I was assigned to work on a strike team dedicated to debugging the race logic in our game. We were responsible for correcting bugs like inconsistent lap counter increments, unreliable direction detection, glitch position tracking, and broken game modes.
The feature list, below, contains the tasks I have worked on.
Architecting the Vehicle
We wanted to allow maximum people to work simultaneously on vehicle, so we architected the vehicle with multiple components. Some of the components and their purpose:
- Hover Force Manipulation
Input Controls Component
Track Features Component
- Boost Ability
- Shield Ability
- Knock Ability
Aside from helping to architect the vehicle, I worked on Input Controls and Track Feature components.
Input Controls Component
The purpose of this component was to provide an interface for the Player Controller and AI Controller. Both of them access following functions to make the vehicle move:
( Accelerate the Car )
( Steer the Car )
Under the hood this component uses stats values like top speed, handling, and acceleration fetched from data tables. The component uses these to set forces and torque according to the input passed through the functions.
( Vehicle Stats )
Integration of Vehicle 2.0
Our team’s first attempt of architecting a vehicle was not quite successful. The vehicle never felt smooth on the track, and it was hard to debug because many forces were applied from different components. The team was having hard time identifying which forces were interfering with each other.
To address the issue my team came up with a different vehicle architecture called 1P1F(1 Point 1 Force), where all the forces are applied as one resultant force from the main component of the vehicle. Isolating the application of forces resulted into a better handling vehicle.
I worked with one other programmer to integrate this system, called Vehicle 2.0. The new vehicle was an experiment developed in a different UE4 project altogether. Many external components like Audio, AI, Special Effects, and Race Logic relied on the variables and functions exposed by the Vehicle.
( Comparison of Blueprint Components )
Switching to Vehicle 2.0 had to be done in a single push of Perforce. This process was successful, and after this push the team of 60 people didn’t even notice that the vehicle was changed under the hood. This kept many people’s workflows uninterrupted.
We made many dependency graphs for this integration.
Track Features Component
The core gameplay of IRL involved track features: Boost, Shield and Knock. I peer programmed these features with another team member. We came up with a framework that relied on timers to activate and deactivate these features.
When a car passed through a Gate or Boost Pad, the logic applies the appropriate ability and it deactivates the effect once its timer goes off. Working with timers made the logic simpler.
( Try apply effect from Gate Pad Blueprint )
( Apply Boost Blueprint )
( Working with Timers )
One of the follow-up requirements was to provide Event Dispatchers for Special Effects and Audio teams, so conveyance for track events could be handled from their side. This involved cleverly calling specific event dispatchers from appropriate places scattered throughout the Track Feature Logic.
You can see all the Event Dispatchers in the screenshot:
( Event Dispatchers related to Track Features )
Bug Fix: Wrong Way Sign
We discovered that if players ended up facing the wrong way on our tracks, they would often go long periods without realizing it. Our game designers decided there needed to be a Wrong Way Sign to let the player know to turn around. Activating the sign and its animation relied on a boolean variable called "isGoingBackwards". This variable was true or false depending on the orientation.
With our first pass at the race logic, this variable sometimes returned an incorrect value. This meant that the sign would pop up even if the player is going forward. The animation would also trigger multiple times, which made the animation look broken.
I fixed the core detection of going in the backward direction by relying on information stored on the keys of the race track spline. I looked for the closest Spline Key from a vehicle's position and returned its forward direction. Using the dot product to determine if the vehicle is facing backward or not made the logic simpler and reliable.
( Forward direction detection Blueprint )
Bug Fix: Lap Counter
Lap Counter was showing inconsistencies because of two issues,
During our alpha milestone the team realized that the scale of the IRL world was humongous. Because of that the max speed of the vehicles was very high and tunneling was happening. Unfortunately, it was too late to scale down everything.
We discovered that the lap count would not increase if the car crosses the finish line with very high velocity. We overcame this issue by making Finish Line a longer volume cube.
(2) Poor detection of finish line crossing:
Making the finish line a large volume meant that the lap count could be increased just by staying still in the volume and rotating the car.
We overcame this issue by making sure that the player crosses the finish volume in the same direction as he entered it. If these directions don't match, the logic wouldn't allow increment or decrement of the lap count.
( Increment/Decrement the Lap Counter Blueprint )
Press Y to reorient the Vehicle
In the Beta stage of development our stakeholders proposed this feature. It was the answer to an annoying situation: "During the race when a player gets knocked by other cars and if ends up facing backwards, manually turning the car around takes more than a couple of seconds." To aid in such situations, we needed a button that orients the car in the forward direction more quickly.
While I was working on Race Logic bug fixes, I used data stored in Keys of the track spline. One of those data values was forward direction on a given Key position. A physics team member who was assigned to work on this feature didn't know about this method of getting the correct forward-facing direction, which was more reliable compared to the alternative solutions.
I ended up providing a helper function which gave other programmers the forward-facing direction with a boolean that tells if the car should reorient itself or not depending on the forward-facing angle passed as an argument. The logic of fetching nearest key on the spline and getting the direction out of it was now simple to use and combined in a single function.
( GetCorrectOrientation function signature )
( GetCorrectOrientation function Blueprint )
When I provided a helper function to someone else, I gave them a debug code as well. As you can see in the GIF, there is a debug line colored green or red depending on whether the car should reorient or not. If the car is within 45 degrees of forward facing direction, the debug line is red, suggesting car doesn't need to reorient; if not, the debug line is green, indicating that the car should reorient.
( GIF showcasing the feature and debug line )
The debug codes made it easier for other team members to build their logic on. Here, if the Y button is pressed and the boolean returned is true, the car ended up reorienting itself to the direction suggested by my function.
What went well?
We all took responsibility for our actions and worked well as a team even though it was the first time for everyone working in such large group.
Peer evaluations were effective: I noticed changes based on feedback in myself, as well as in others.
According to the workload, shifting individuals to different teams worked well!
During critical integration(s) and bug fixes, I enjoyed buddy-coding/peer-programming. It produced higher quality results.
End of the day activities: “Show-n-tell” and “Two claps of appreciation,” which highlights completed tasks, was motivating.
What went wrong?
During alpha, handling stress was challenging; I also faced bursts of self-criticism.
For implementing new features, following the pipeline is essential! One time I missed that mark when a GD (game designer) requested a new feature, to me, which was not backed by the GDD (game design document).
Feature creep happened, alongside frequent ongoing changes in the gameplay. During this time, playtesting the game was given lesser importance than it should have been.
What did I learn?
Balancing the work and personal life helps a lot with stress, as well as it increases morale. A context switch is refreshing.
Saying NO, at right places, is very important; as well as following the pipeline, especially when confused.
Playtesting the game and submitting bugs to Jira is a good use of time. :)