Nov. 2019 - Jun. 2020
/// Battle Cars
Graduation project - Supinfogame (team of 7)
Battle Cars is my graduation project (5th year). It is a Battle Royale car game made for 64 players. They must go from one arena to the other, until they reach the last one and destroy every opponent. Violent high speed collisions, game changing abilities, spectacular tricks... In short ; total destruction until only one remains.
On this project, I was lead designer & gameplay programmer (more details and car physics design breakdown below).
>. Lead designer
As the vision owner of this project, I had to make sure the other members of the team were on the same page and had the same vision of the game. My role was to unify the team's creativity.
I wrote many feature documents to describe the features I designed for the game. These short documents were written with one objective in mind:
Making my colleagues' work easier: listing variables and conditions for programmers, creative intentions and references for designers and artists...
Well detailed and rational design-oriented documentation removed any ambiguity and made the workflow much more efficient. Programmers knew exactly how to implement a feature after reading its document.
You can read more about Battle Cars (and check more documentation) in our internal wiki:
Spectator mode document summary
(click to zoom-in)
Air time trick feature document extracts
(click to zoom-in)
>. Gameplay programmer
As the gameplay programmer on this project, my role was also to implement the 3C related features of the game.
I always aimed for short and specific scripts, for them to be as modular as possible. This offered a great code re-usability and helped maintain the project's tidiness.
My second focus was to make readable code, that could be picked-up by other programmers and understood with few to no explanations.
Also, coding the features myself helped and still helps me better understand the programmers' expectations and needs regarding feature documentation.
Component: Car's suspension
(click to zoom-in)
Once again, I always planned on making my colleagues work easier.
Here, the designers could easily tweak the car's variables, with no coding required. They just had to read the tooltips that told them what changing a value would do, and how that would impact the feature.
Also, a feature couldn't be broken by accident. This was achieved thanks to error-proof interfaces.
The workflow may never be slowed down!
Some scriptable objects, containing various data.
(click to zoom-in)
>. Breakdown of the car's physics
Battle Cars was developped on Unity 3D, and uses its physics engine to move the player's car around.
However, with the intention of having more control over the game's core feature,
I have developped my own scripts in order to fake some key elements.
This was necessary in order to achieve the intended gameplay; the car had to be nervous, reactive and powerful,
all of that while remaining plausible and coherent.
Here is the breakdown of Battle Cars' physics design, in 4 crucial points.
I. Faking the wheel and suspension systems
First of all, the car's game object does not include a "wheel collider system", which would be physicly correct but way too complex for balancing and embellish for our intended arcady and nervous driving.
No, instead of that, the car's object "floats" in the air, just like a hoverboard would.
Thanks to a Raycast system, that are projected towards the ground, each "suspension" applies an upwards force at its location on the car. The closer this point gets to the ground, the greater the applied force.
This actually is quite close to how real suspension springs work.
Each suspension component is located at the center of the corresponding wheel's visual mesh, as you can see in the screenshot below.
Below are the four lines of code that are called at each physics frame, on each suspension in the car.
(Front Left, Front Right, Rear Left, Rear Right)
As you can see in the code snippet above, I have also implemented some damping into the system.
In order to avoid the car being extra bouncy and thus perfectly uncontrollable, I've added a damping variable. This variable gives some inertia to the value of the upwards force that is applied to the vehicle.
This results in a way more realistic (or at least believable) car, as well as smoother suspension springs.
It was obviously essential for me and the team to be able to adjust all the variables quickly and efficiently.
This is why I have gathered them all into Scriptable Objects, which are super easy to create and modify by the involved designers.
All these parameters can be adjusted during runtime, so it was fairly easy to fine-tune the vehicles along the production.
Another faking I had to do in order to make driving more enjoyable was to make the "suspensions" more or less stiff depending on the vehicle's speed.
Thus, in Battle Cars, a car that's going at a low speed will have softer suspensions, enhacing and showcasing mass transfers, building up to more dynamism for the vehicle, which as a result gets a swinging forwards motion when braking, or a backwards one when accelerating, for instance.
The benefit at higher speeds is that contacts between the car's collision mesh and the ground are reduced, so everything is more stable and steady.
II. Applying forces along the ground's normal vector
During the first implementation of my fake suspension system, I had quickly noticed a major issue that would negatively impact the driving.
The acceleration and braking forces of the car were applied in the direction of its forward vector, which resulted in a floaty-feeling car. Even though this was more realistic, it absolutely did not correspond to our design intentions.
What I was after was a driving that was much closer to the ground. The car had to be "sucked" into the ground, in order to increase the dynamism and the nervousness of the driving.
The solution here was to take into account the normal vector of the surface on which the car was when applying forces to it.
Here is the function I was using to get the car's forward vector, adjusted to the ground's normal.
The value of each "GroundNormal" variable is obtained thanks to the Raycast of its relative suspension component.
III. Dynamic gravity force
The default gravity force did not allow for the driving sensations I aimed for.
The car had a tendency to stay airborne for too long. This is why I decided to disable the initial gravity, included in Unity's physics engine, and wrote my own gravity force script.
This allowed me to apply a different gravity force for each vehicle if I wanted to, but mostly to apply a force that was relative to the vehicle's state; wheter is was airborne or on the ground.
Once again, here are the different variables, grouped into a Scriptable Object.
IV. Applying the physics forces at the right places
Now that I've showed you the several forces applied onto the car, it's now time to talk about force locations. Those forces are rarely ever applied into the car's center of mass.
In order to create a realistic feeling around the car, while keeping a fair control over the physics, I've decided to apply the forces with a certain offset from the vehicle's center of mass.
The blue dot/circle represents the location where the forces in the forward axis of the vehicle are applied (acceleration, braking, air drag).
The red dot/circle represents the location where lateral forces are applied (steering, drifts, wheel friction).
As you can see, those are not located at the center of the vehicle.
When a force is applied on a location that's offset from the center of mass of an object, a torque is generated.
Is is thanks to this volontary imbalance that the car leans forwards when braking or backwards when accelerating, or sideways when cornering.
The whole controller then felt more dynamic and way less rigid than before those changes.
To go even further with these principles, I have made those point's locations dynamic. Meaning that their position on the car change, depending on the car's speed.
Here (above), for the forward vector forces, the location where the forces are applied goes from the dark blue dot when the car is stopped to the light blue dot when the car is at its full speed.
Below, we can see the same interpolation principle for the location where the lateral forces are applied, from the red dot to the orange dot.
Changing the location of where the forces are applied on the vehicle enables a greater control over the car's overall stability, as well as it's rigidity or smoothness, depending on how the car is expected to behave.
Finally, as you can see on the adjacent Scriptable Object screenshot, the drag and friction forces are once again faked.
I have deactivated those forces on Unity's base physics engine, in order to apply them myself with a custom script, enable more accuracy and control; I can apply each force seperately on each axis, which Unity physics don't initially allow.
Here's a snippet of the functions being called on each physics frame for the vehicle, regarding drag and friction forces.
Here's a fonction that enables me to apply a friction force on one axis only (forward axis on this example), with a greater or smaller intensity depending on the car's state (airborne, on the ground).
Here, another function, enabling me to apply a given force of angular drag, once again, on only one chosen axis.
Thanks for reading through this breakdown.
I would be glad to chat about this with you, please reach out if you'd like to know more!
In the meantime, here's the full video presentation of our beloved project.