Made for: ARU 2nd Year (during 1st Year Semester 2)
Duration: 3 Months
Engine: Unity 2017.3.1f1
Language: C#
Position: Lead Programmer
Brief (excerpt from Codemasters introduction):
“Codemasters are synonymous with racing games, from F1 to DiRT Rally, from MicroMachines to GRID. Now we’d like you to create a Racing Game. What you race is up to you. It doesn’t have to be cars, it could be ostriches, or trucks, or fireflies, whatever you choose.”
Note:
This second year module gave groups of programmers the opportunity to work with groups of artists on another course. Since this collaboration was optional, some programmers dropped out leaving a group of artists on their own. Three of us from first year were called in to participate without accreditation and submission.
Since we joined 3 weeks in, the concept was already decided by the artists.
The Game

PlanetTracks is a couch-competitive racing game where up to 4 players navigate tanks around a rotating planet trying to reach the finish line first.
Players must pass though a series of checkpoints on their journey placed in a variety of randomly spawning planet segments. Failing to reach a checkpoint or falling behind results in an elimination.
Each tank is equipped with a cannon that can stun other players for a brief period and clear incoming obstacles.
Power-ups are also added to the mix giving games more unpredictability and excitement.
6 different Tanks can be chosen from, 2 in each class. The light class has more acceleration but struggles with moving through obstacles. Heavy tanks can plough through props but take longer to reach top speed. Medium tanks occupy a middle ground between the two.
What I did
Movement
Initially I was tasked with creating the movement system. This was by far the most complicated part of the project for me. Getting a tank to move around a planet while conforming to uneven terrain was a nightmare and basic approaches were just not cutting it.
I first tried to calculate the position mathematically with the player input modifying the spherical position of the tank directly. This caused problems with stopping the player when they hit obstacles and changing the speed when moving on slopes.
This meant the system needed to rely on physics somehow. Adding a force to move the tank while a gravity force acted towards the center of the planet seemed to be the solution. The problem with this approach was the shape of the collider. If I used a box, it would get stuck on uneven terrain and steps. A capsule was smoother but it still “sea-sawed” over mounds and dragged across dips. This is compounded by the fact that the tank will always be on a curved surface.
The problem was the distribution of weight of the vehicle itself. A real tank has many wheels that use suspension to conform its tracks in order to touch as much of the ground as possible. To simulate this, I used Unitys join system which is calculated using Nvideas PhysX engine.
To start with I used 3 capsules that lay horizontal to the tracks. Each capsule could move vertically on the tanks Y axis and was pulled towards the planet with a gravity force. This system started actually showing results so I spend time adjusting the joint constraints to ensure it worked smoothly.

To increase the accuracy of the movement, I split each capsule in two, one piece for each track. This allowed each side of the tank to act independently of one another.

While all this physics stuff was going on, I was also working on how the input translated to movement. Since the player would be moving and aiming at the same time, I wanted to limit input to a single joystick. As this was also a party game, the way the tank moves should be instantly attainable. It should also be somewhat representative of how a real tank would move.
My idea was to have the desired direction of the tank be determined by the position of the stick. The tank would turn towards where the stick was pointing while moving. The speed of forward movement would be dictated by the scale of the stick input. This allows the tank to move slower when turning towards a wider angle and vice versa.
I chose this approach since it allowed the player to alternate between turning quickly and moving forwards quickly. This also mirrors real tank movement since tuning on the spot is faster than turning at high speed due to the individual track forces.
The option to reverse was also tested at this stage but was decided against to incentivize forwards movement around the planet.

This tank control code can be found below:
_throttle = _inputVector.magnitude;
_inputVector.Normalize();
// Position in direction of the input vector, rotated to face the camera
Vector3 MovePosition = transform.position + (CameraTransform.rotation * Quaternion.Euler(-90, 0, 0)) * _inputVector * 0.2f;
// Align to the surface of the planet curvature
Vector3 AlignedMovePosition = ProjectPointOnPlane(transform.position, transform.position, MovePosition);
// Directional rotation destination vector
Vector3 TargetDirection = AlignedMovePosition - transform.position;
// Angle used to calculate speeds
_relativeSlipAngle = Vector3.Angle(transform.forward, TargetDirection);
// Turning
if (_inputVector.magnitude > 0)
{
// Limit turning to 90 degrees left and right
if (Vector3.Dot(AlignedMovePosition - transform.position, transform.forward) < 0) // Destination behind
{
if (Vector3.Dot(AlignedMovePosition - transform.position, transform.right) > 0) // Destination to the right
{
TargetDirection = transform.right;
}
else
{
TargetDirection = -transform.right;
}
}
float ScaledRotationSpeed = (RotationSpeed + (_relativeSlipAngle / 90) * RotationByAngle) / InhibitTurnRate * Time.deltaTime, 0.0f);
// Rotate the tank to face the target direction
transform.LookAt(transform.position + Vector3.RotateTowards(transform.forward, TargetDirection, ScaledRotationSpeed, transform.position);
}
Then the forces are applied. An additional force is applied to the back of the tank to stop it tipping forward or flipping over. The constraints on the wheels also need to lock to stop the tank from moving when there is no input.
Velocity += (_throttle * (MovementSpeed - (_relativeSlipAngle / 90) * InverseMovementByAngle) * Acceleration) * Time.fixedDeltaTime;
Velocity = Mathf.Clamp(Velocity, 0f, ThrottleCurve.Evaluate(_throttle) * TopSpeed);
if(_inputVector.magnitude > 0) {
PhysBody.velocity = transform.forward * Velocity;
BackForce.GravityMultiplier = Mathf.Lerp(0f, 230f, Velocity / TopSpeed);
if(_stationary) {
_stationary = false;
Velocity = InitialSpeed;
LockWheels(false);
}
} else {
PhysBody.velocity = Vector3.zero;
Velocity = 0;
BackForce.GravityMultiplier = 0;
if(!_stationary) {
_stationary = true;
LockWheels(true);
}
}
Planet Generation
A random segment is picked from a possible 7 and added to the world when it reaches the side of the planet opposite the camera. Since instantiating segments while the game was running was causing performance issues, I decided to instantiate all of them at the start of the game and active them in order they are needed. I also gave the script some editor-facing features such as spawn percentage curves, progress bars and visual indicators for each segment.

UI and Menus
The In-Game portrait displays and main menu were based off reference material and textures provided by the artists. All transitions are animated and button presses shown visually.

The selection screen allows players to cycle through available tanks and “ready up” before the game begins.

I also implemented a pause menu that can be controlled by the player that pressed start.

Prop Interaction
Most small objects can be hit and destroyed causing the tank to loose some speed and bounce based on a defined scale. Objects like trees fall away from the player and cause a moderate impact force. Buildings cause a larger impact and sink into the ground. These props can also fall due to explosions from tank shells.

Particles
I also made many of the particles in the game. Most effects use sprites provided by the artists and some are based on reference material to achieve the results they wanted to see. A range of these effects can be found below:

Destruction effects 
Planet brace flames 
Lava pool and volcano 
Stun and boost 
Charge up 
EMP 
Firing 
Normal shot 
Power shot 
Mine activation and explosion
Some segments needed overall effects like the embers on the lava segment.

Tank movement also creates particles that vary based on track speed and ground type.
And More
Other areas I worked on were the final version of the checkpoint system, the main camera and tank shaders (with help from a lecturer) as well as being the main intermediary between the artists and engine. Most of their models and textures were provided through trello which I downloaded, implemented into Unity and adjusted based on feedback. I also created tools to help the artists place and manipulate props on the surface of each segment.
The Outcome
The project was also created for a final presentation to a panel of industry figures. It was positively received by both the panel and lecturers.



