Project Description

Published On: January 24th, 20230 Comments

GAM 606, Rapid Game Development; Racing Game

This assignment took some interesting twists and turns on its way through development. Originally, the goal was to create something like a 2D version of Forza Horizon’s Drift Zones, where the goal is to rack up as many drift points as possible between two checkpoints, while still crossing the finish point under an allotted time. With this, the DriftMeter at the bottom originally was a Points Multiplier, basically approximating a DriftStreak and giving you inflated rewards the more tricks you performed. However, the concept never really popped — most likely because a mechanic like Forza’s requires constantly pinging and popping rewards and feedback to the player (the casino/slot machine effect). Since this was beyond the purview of a 48-hour gamejam (how I approached the projects in this class), I had to look for alternatives. Because the car’s mass is set fairly high to prevent any strange Unity Physics behavior on collision, it turns out that the enemy AI doesn’t have to be much more complicated than simply steering towards the next point in a series of points — it’s too hard to knock the enemy AI off course!

The project’s base car controller comes from a PrettyFlyGames tutorial available on Youtube. The Youtube tutorial keeps going beyond what’s represented in this project, including multiplayer and touch support, so check that out!

Programming Notes

Originally I planned to let you hold down Spacebar to increase your drift with the e-brake by adding extra velocity to the car’s transform.right, but it turned out the control was much more enjoyable if the e-brake was on all the time! You can test out the original handling still by holding down Spacebar (the IsEbrakeOn logic is reversed).

void ApplyEngineForce()
{
	//Apply drag if there is no accelerationInput so the car stops when the player lets go of the accelerator
	if (accelerationInput == 0)
		carRigidbody2D.drag = Mathf.Lerp(carRigidbody2D.drag, 3.0f, Time.fixedDeltaTime * 3);
	else carRigidbody2D.drag = 0;

	//Caculate how much "forward" we are going in terms of the direction of our velocity
	velocityVsUp = Vector2.Dot(transform.up, carRigidbody2D.velocity);

	//Limit so we cannot go faster than the max speed in the "forward" direction
	if (velocityVsUp > maxSpeed && accelerationInput > 0)
		return;

	//Limit so we cannot go faster than the 50% of max speed in the "reverse" direction
	if (velocityVsUp < -maxSpeed*0.5f && accelerationInput < 0)
		return;

	//Limit so we cannot go faster in any direction while accelerating
	if (carRigidbody2D.velocity.sqrMagnitude > maxSpeed * maxSpeed && accelerationInput > 0)
		return;

	//Create a force for the engine
	Vector2 engineForceVector = transform.up * (accelerationInput * accelerationFactor);

	//Apply force and pushes the car forward
	carRigidbody2D.AddForce(engineForceVector, ForceMode2D.Force);

	if (eDrift) return;
	
	//Create a force for the edrift
	Vector2 eDriftVector = transform.right * (accelerationInput * accelerationFactor);
	carRigidbody2D.AddForce(eDriftVector, ForceMode2D.Force);
}

The Enemy AI steers using Transform.InverseTransformPoint to calculate a new steering angle and input vector to reach the AI’s next checkpoint.

Vector3 relativeVector = transform.InverseTransformPoint(points[pointIndex].position);
float newSteer = (relativeVector.x / relativeVector.magnitude) * 1f; // 1f = maxSteeringAngle delta per tick

Play/Download

Project Details

Skills Needed:

Categories:

By:

Project Images

lightmaze.
Hell's Playground

Leave a Reply

Share This: