Build an Arcade Racing Game in Unity

Build a drift-to-boost arcade racing prototype with mobile touch controls.

Introduction

30 Second Summary

Racing games feel amazing because of tiny, deliberate details. The way a car slides around corners, the rush of speed when you hit boost, the satisfying camera effects that sell velocity. Game developers carefully engineer every force and visual effect to create that sensation.

In this project, you will build an arcade racing prototype in Unity that captures the drift-to-boost mechanic from games like Burnout Paradise. You'll create a driveable car with satisfying physics, a boost system that rewards risky drifting, and mobile-ready touch controls.

What You'll Build

A "Burnout Drift" racing prototype featuring a sphere-based Rigidbody car controller, drift detection, a fill-by-drifting boost meter with camera juice effects, and on-screen touch controls configured for Android export.

By the end of this project, you'll have:

  • A driveable arcade car with responsive physics that accelerates, steers, and drifts with satisfying handling.
  • A working drift-to-boost system where drifting fills a boost meter and activating boost triggers FOV widening and speed particles.
  • On-screen mobile touch controls and a build-ready project configured for Android export.
  • Secret Mission: Add AI traffic cars to dodge, with a near-miss boost bonus when you barely avoid them.

Are there any prerequisites?

No prior Unity or game development experience is needed. This project walks you through installing Unity Hub, Unity 6.3 LTS, and all required build modules from scratch. You just need a Windows 10 or newer PC capable of running Unity.

Install Unity and Create the Project

Every racing game starts with a blank project. With Unity Hub ready and Unity 6.3 LTS installed, you can now create the project that will hold your arcade car, track, and boost system.

Unity projects start from templates that pre-configure your rendering pipeline and default settings. You'll use the Universal 3D template, which sets up the Universal Render Pipeline (URP) for efficient mobile performance out of the box.

In this step, get ready to:
  • Create a new Unity project using the Universal 3D (URP) template.
  • Confirm the Unity Editor opens with your BurnoutDrift project loaded.
Create the BurnoutDrift project
  • In Unity Hub, click New Project in the top-right corner.
  • In the template list on the left, select Universal 3D.
  • In the Project name field on the right side, type BurnoutDrift.
  • Leave the location as the default, or choose a folder you'll remember (like your Desktop).
  • Click Create project.

What is URP?

The Universal Render Pipeline is Unity's rendering system optimized for cross-platform performance. It handles lighting, shadows, and materials in a way that works well on mobile devices without sacrificing visual quality on desktop.

By choosing the Universal 3D template, your project is already configured for the mobile build you'll create at the end of this project.

Unity will take a minute or two to generate the project files and open the Editor. You'll know it's ready when you see the Unity Editor with its Scene view, Game view, Hierarchy panel, and Inspector panel loaded.

Editor not opening or stuck loading?

The first project creation can take several minutes as Unity compiles shaders and imports default assets. Give it up to 5 minutes before assuming something is wrong.

If the Editor fails to open, close Unity Hub, reopen it, and try creating the project again. Make sure your disk has at least 5 GB of free space.

Help me troubleshoot why my Unity project won't open.

Your project is ready. Next up, you'll build a looped track and set up the physics-driven car that will tear around it.

Build the Track and Car Setup

With Unity open and your BurnoutDrift project loaded, you need something for the car to drive on and a car to drive.

In this step, you'll build a simple oval track out of Unity primitives, create an invisible physics sphere that drives the car, and set up a chase camera that smoothly follows the action.

In this step, get ready to:
  • Build a looped track with road surfaces and barriers.
  • Create a physics-driven car using a hidden sphere and a visual car model.
  • Set up a smooth chase camera that follows the car.
Create the track

Racing games need a track for the car to drive on. You'll build a simple oval loop using stretched Planes for the road and Cubes for the barriers along the edges.

  • In the Hierarchy panel (left side of the Unity Editor), right-click in an empty area.
  • Select Create Empty.
  • Name this new GameObject Track. This will be the parent container for all your track pieces.

Now add the road surface pieces inside the Track object.

  • Right-click on the Track GameObject in the Hierarchy.
  • Select 3D Object then Plane.
  • In the Inspector panel (right side), set the Plane's Transform Scale to X: 10, Y: 1, Z: 30. This stretches it into a long road segment.
  • Duplicate this Plane by pressing Ctrl+D (Windows) or Cmd+D (macOS).
  • Rotate the duplicate 90 degrees on the Y-axis (set Rotation Y to 90 in the Inspector).
  • Position the two planes so their ends overlap slightly, forming half of an oval shape.
  • Duplicate both planes again and position the copies to close the loop into a full oval track.

Keep it simple

Your track does not need to be geometrically perfect. The goal is a closed loop the car can drive around continuously. You can adjust positions later once the car is moving.

Next, add barriers along the edges so the car cannot fall off the track.

  • Right-click on Track in the Hierarchy.
  • Select 3D Object then Cube.
  • Scale the Cube to be long and thin (for example, Scale X: 0.5, Y: 2, Z: 30) and position it along one edge of the road.
  • Duplicate the barrier Cube and position copies along both edges of every road segment.

Finally, apply materials to visually distinguish the road from the barriers.

  • In the Project window at the bottom, right-click inside the Assets folder.
  • Select Create then Material. Name it RoadMaterial.
  • In the Inspector, click the color swatch next to Base Map and choose a dark grey or black colour.
  • Drag RoadMaterial from the Project window onto each road Plane in the Scene view.
  • Create a second Material named BarrierMaterial with a bright colour (red or orange works well).
  • Drag BarrierMaterial onto each barrier Cube.

What did you just build?

You created a simple oval track using Unity's built-in 3D primitives. The stretched Planes form the driveable surface. The raised Cubes act as walls to keep the car on the road.

Materials give each surface a distinct colour so you can easily see where the road ends and the barriers begin.

Create the car

Arcade racing games often use a hidden sphere for physics and a separate visual model that follows it. The sphere rolls and collides predictably, while the car model rotates and tilts for visual flair.

  • Right-click in an empty area of the Hierarchy panel.
  • Select 3D Object then Sphere.
  • Position the Sphere above the track surface (set Position Y to 1) so it does not spawn inside the road.
  • In the Inspector, uncheck the Mesh Renderer component checkbox to make the sphere invisible. The sphere handles physics only.

Now add the physics component that makes the sphere respond to forces.

  • With the Sphere selected, click Add Component at the bottom of the Inspector.
  • Search for Rigidbody and click it to add the component.
  • In the Rigidbody component, set Mass to 1.
  • Set Linear Damping to 1.
  • Set Angular Damping to 0.5.

Why use a hidden sphere?

A sphere collider is the most predictable shape for physics. It rolls smoothly over surfaces and does not catch on edges. The car model is purely visual and follows the sphere's position each frame.

Linear Damping slows the sphere's movement over time (like air resistance). Angular Damping slows rotation. Together they give the car a responsive, arcade-like stop-and-go feel.

Now build the visual car model that will follow the sphere.

  • Right-click in the Hierarchy and select Create Empty. Name it CarModel.
  • Right-click on CarModel and select 3D Object then Cube. This is the car chassis.
  • Scale the chassis Cube to look like a car body (for example, Scale X: 2, Y: 0.5, Z: 4).
  • Add four more child Cubes under CarModel to represent wheels. Scale each wheel to approximately X: 0.5, Y: 0.5, Z: 0.5.
  • Position the wheel Cubes at the four corners of the chassis, slightly below it.
  • Position CarModel at the same location as the Sphere so it visually overlaps.

What should I see?

In the Scene view, you should see a box-shaped car made of Cubes sitting on your dark track. The sphere is invisible (Mesh Renderer off) but you can see its wireframe outline if you select it. The barriers line the edges of the oval road in a bright colour.

Car model floating or buried in the track?

Adjust the Position Y of both the Sphere and CarModel until the wheels sit just on top of the road surface. A Y position of about 1 usually works.

Help me position my car model on the track surface.

Set up the chase camera

A chase camera follows behind the car and looks at it, creating the classic third-person racing view. You'll create a camera rig and write a short script to smoothly follow the physics sphere.

  • Right-click in the Hierarchy and select Create Empty. Name it CameraRig.
  • Find Main Camera in the Hierarchy. Drag it onto CameraRig to make it a child object.
  • Position CameraRig behind and above the Sphere (for example, Position X: 0, Y: 5, Z: -10 relative to the sphere's position).

Now create the script that makes the camera follow the sphere smoothly.

  • In the Project window, make sure the Assets folder is selected.
  • Go to the main menu and click Assets then Create then Scripting then MonoBehaviour Script.
  • Name the script CameraFollow and press Enter.
  • Double-click CameraFollow to open it in Visual Studio.
  • Delete all the default code in the file and replace it with the following:
using UnityEngine;

public class CameraFollow : MonoBehaviour
{
    // The target transform to follow (assign the Sphere here)
    public Transform target;
    // Offset position relative to the target
    public Vector3 offset = new Vector3(0f, 5f, -10f);
    // How quickly the camera moves to the desired position
    public float followSpeed = 5f;
    // How quickly the camera rotates to look at the target
    public float lookSpeed = 10f;

    private void LateUpdate()
    {
        // Skip if no target is assigned
        if (target == null) return;

        // Calculate where the camera should be based on target rotation and offset
        Vector3 desiredPosition = target.position + target.rotation * offset;
        transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);

        // Smoothly rotate to look at the target
        Quaternion desiredRotation = Quaternion.LookRotation(target.position - transform.position);
        transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, lookSpeed * Time.deltaTime);
    }
}

What does this code do?

`LateUpdate()` runs after all other updates each frame, which prevents the camera from jittering when the physics sphere moves.

`Vector3.Lerp` smoothly blends the camera's current position toward its desired position each frame. `Quaternion.Slerp` does the same for rotation. Together they create a camera that glides behind the car rather than snapping rigidly to it.

  • Save the file in Visual Studio (Ctrl+S on Windows, Cmd+S on macOS).
  • Switch back to the Unity Editor. Wait for the script to compile (the spinner in the bottom-right corner stops).
  • Select CameraRig in the Hierarchy.
  • Drag the CameraFollow script from the Project window onto CameraRig in the Inspector to attach it as a component.
  • In the CameraFollow component in the Inspector, drag the Sphere from the Hierarchy into the Target field.
  • Confirm the Offset is set to X: 0, Y: 5, Z: -10.
  • Confirm Follow Speed is 5 and Look Speed is 10.

Press the Play button at the top of the Editor to test. The sphere should fall onto the track and the camera should follow it.

Camera not following the sphere?

Make sure you dragged the Sphere (not CarModel) into the Target field on the CameraFollow component. Also confirm the script compiled without errors by checking the Console window (Window then General then Console).

Help me fix my CameraFollow script not working.

✔️ Awesome, I've got everything!

Great. Double check you saved CameraFollow.cs and that it compiled without errors in the Console.

ⓧ I'd like to double check the full code

Here is the complete CameraFollow.cs file:

using UnityEngine;

public class CameraFollow : MonoBehaviour
{
    public Transform target;
    public Vector3 offset = new Vector3(0f, 5f, -10f);
    public float followSpeed = 5f;
    public float lookSpeed = 10f;

    private void LateUpdate()
    {
        if (target == null) return;

        Vector3 desiredPosition = target.position + target.rotation * offset;
        transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);

        Quaternion desiredRotation = Quaternion.LookRotation(target.position - transform.position);
        transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, lookSpeed * Time.deltaTime);
    }
}

Your track is built, the car is ready for physics, and the camera knows how to follow the action. Next up, you'll write the car controller script that makes the sphere accelerate, steer, and drift.

Write the Arcade Car Controller

Your track is laid out and the invisible physics sphere is ready to roll. Right now though, pressing any key does nothing.

In this step, you'll write the CarController script that reads player input and translates it into forces. By the end, your car will accelerate, steer, and detect when it's drifting sideways.

In this step, get ready to:
  • Create a CarController script with acceleration and steering physics.
  • Detect drift by measuring sideways velocity.
  • Add dynamic drag and gravity for arcade-style handling.
Create the script and implement acceleration and steering

The sphere-based physics approach works by applying forces to a hidden sphere, then having a visible car model follow its position. This gives you direct, predictable control over movement without the complexity of wheel physics.

  • In the Project window at the bottom of the Unity Editor, right-click inside the Assets folder.
  • Select Create > C# Script.
  • Name the script CarController and press Enter.
  • Double-click CarController.cs to open it in Visual Studio.
  • Delete all the default template code. Replace it with this class structure and physics helper methods:
using UnityEngine;
using UnityEngine.InputSystem;

public class CarController : MonoBehaviour
{
    [Header("Car Settings")]
    public float acceleration = 30f;
    public float steering = 80f;
    public float maxSpeed = 50f;
    public float groundDrag = 3f;
    public float airDrag = 0.1f;
    public float gravityForce = 20f;

    [Header("Drift Settings")]
    public float driftThreshold = 2f;

    [Header("References")]
    public Transform carModel;
    public InputActionReference steerAction;
    public InputActionReference accelerateAction;

    private Rigidbody rb;
    private bool isGrounded;
    private float steerInput;
    private float accelInput;

    public bool IsDrifting { get; private set; }
    public float DriftFactor { get; private set; }

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void OnEnable()
    {
        steerAction.action.Enable();
        accelerateAction.action.Enable();
    }

    private void OnDisable()
    {
        steerAction.action.Disable();
        accelerateAction.action.Disable();
    }

    private void CheckGround()
    {
        isGrounded = Physics.Raycast(transform.position, -transform.up, 1.2f);
    }

    private void ApplyAcceleration()
    {
        if (!isGrounded) return;
        if (rb.linearVelocity.magnitude >= maxSpeed) return;

        Vector3 force = transform.forward * accelInput * acceleration;
        rb.AddForce(force, ForceMode.Acceleration);
    }

    private void ApplySteering()
    {
        if (!isGrounded) return;
        if (rb.linearVelocity.magnitude < 1f) return;

        float turnAmount = steerInput * steering * Time.fixedDeltaTime;
        Quaternion turnRotation = Quaternion.Euler(0f, turnAmount, 0f);
        rb.MoveRotation(rb.rotation * turnRotation);
    }
}

What does this code do?

This sets up the foundation of your arcade car controller.

  • The [Header] attributes group your settings in the Unity Inspector for easy tuning.
  • InputActionReference fields let you plug in Input System actions from the Inspector without hardcoding key bindings.
  • CheckGround() fires a short raycast downward. If it hits something within 1.2 units, the car is grounded and allowed to steer.
  • ApplyAcceleration() pushes the sphere forward using rb.AddForce(), but only when grounded and below max speed.
  • ApplySteering() rotates the Rigidbody by a turn amount each physics frame. The car must be moving (velocity > 1) to turn, preventing unrealistic spinning in place.

Why sphere-based physics instead of WheelColliders?

Unity's WheelCollider component simulates realistic suspension, tire friction curves, and slip angles. That's powerful for racing sims but overwhelming for an arcade game.

The sphere approach gives you direct control over forces and drag with minimal code. The result feels snappy and responsive, which is exactly what arcade racers like Burnout prioritize.

  • You won't see movement yet. The next substep adds the Update loop that reads input and feeds it to these methods.
Implement drift detection in the Update loop

Drift detection is the core mechanic that powers the boost system later. The idea is simple: measure how fast the car is moving sideways. If it exceeds a threshold, the car is drifting.

  • In CarController.cs, add this Update method after the OnDisable() method and before CheckGround():
    private void Update()
    {
        Vector2 steerValue = steerAction.action.ReadValue<Vector2>();
        steerInput = steerValue.x;
        accelInput = accelerateAction.action.ReadValue<float>();

        if (carModel != null)
        {
            carModel.position = rb.position;
            carModel.rotation = Quaternion.Slerp(carModel.rotation, rb.rotation, Time.deltaTime * 10f);
        }

        float sidewaysSpeed = Mathf.Abs(Vector3.Dot(rb.linearVelocity, transform.right));
        IsDrifting = sidewaysSpeed > driftThreshold && isGrounded;
        DriftFactor = IsDrifting ? sidewaysSpeed / 10f : 0f;
    }

What does this code do?

Update runs every visual frame and handles three jobs:

  • Reads input from the Input System. The steer action gives a Vector2 (we use only the X axis for left/right). The accelerate action gives a float (0 or 1 for gas).
  • Syncs the visible CarModel to the sphere's position. Quaternion.Slerp smooths the rotation so the car body doesn't jitter.
  • Detects drifting using Vector3.Dot(rb.linearVelocity, transform.right). This dot product measures how much velocity is pointing sideways. When it exceeds driftThreshold (2 units/s), the car is officially drifting.

Why linearVelocity instead of velocity?

In Unity 6, Rigidbody.velocity was renamed to Rigidbody.linearVelocity. The old name still works as a deprecated alias, but using the new name avoids compiler warnings.

  • The car still won't move because FixedUpdate isn't calling the physics methods yet. The next substep wires everything together.
Add dynamic drag and gravity

Arcade racers feel responsive because they use high drag on the ground (quick stopping) and low drag in the air (satisfying jumps). You'll also add extra downward gravity so the car feels planted and doesn't float.

  • In CarController.cs, add the FixedUpdate, ApplyDrag, and ApplyGravity methods after ApplySteering(). FixedUpdate is the orchestrator that calls all your physics methods each physics tick:
    private void FixedUpdate()
    {
        CheckGround();
        ApplyAcceleration();
        ApplySteering();
        ApplyDrag();
        ApplyGravity();
    }

    private void ApplyDrag()
    {
        rb.linearDamping = isGrounded ? groundDrag : airDrag;
    }

    private void ApplyGravity()
    {
        if (!isGrounded)
        {
            rb.AddForce(Vector3.down * gravityForce, ForceMode.Acceleration);
        }
    }

What does this code do?

  • FixedUpdate() runs at a fixed interval (default 50 times/second) and is where all physics operations belong. It calls each helper method in sequence.
  • ApplyDrag() switches linearDamping between 3 (grounded) and 0.1 (airborne). High ground drag makes the car stop quickly when you release the accelerator. Low air drag lets jumps feel floaty.
  • ApplyGravity() adds 20 units of extra downward force when airborne. Unity's default gravity (9.81) feels too slow for arcade games, so this extra pull keeps the car grounded and responsive.
  • Save CarController.cs in Visual Studio (Ctrl+S).
  • Switch back to the Unity Editor. Wait for the script to compile (the loading spinner at the bottom-right disappears when done).

Seeing compile errors?

  • If you see an error about InputSystem not being found, confirm the Input System package is installed. Go to Window > Package Manager, search for Input System, and verify it shows as installed. Unity 6 projects include it by default, but it may need to be re-enabled.
  • If you see an error about linearVelocity or linearDamping, make sure you're using Unity 6.3 LTS. These property names replaced the older velocity and drag names.
  • Check that FixedUpdate is placed AFTER ApplySteering() but still inside the class braces.

Help me fix a compile error in my CarController script

✔️ Awesome, I've got everything!

Great. Make sure you've saved CarController.cs and the Console shows no errors.

ⓧ I'd like to double check the full code

using UnityEngine;
using UnityEngine.InputSystem;

public class CarController : MonoBehaviour
{
    [Header("Car Settings")]
    public float acceleration = 30f;
    public float steering = 80f;
    public float maxSpeed = 50f;
    public float groundDrag = 3f;
    public float airDrag = 0.1f;
    public float gravityForce = 20f;

    [Header("Drift Settings")]
    public float driftThreshold = 2f;

    [Header("References")]
    public Transform carModel;
    public InputActionReference steerAction;
    public InputActionReference accelerateAction;

    private Rigidbody rb;
    private bool isGrounded;
    private float steerInput;
    private float accelInput;

    public bool IsDrifting { get; private set; }
    public float DriftFactor { get; private set; }

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void OnEnable()
    {
        steerAction.action.Enable();
        accelerateAction.action.Enable();
    }

    private void OnDisable()
    {
        steerAction.action.Disable();
        accelerateAction.action.Disable();
    }

    private void Update()
    {
        Vector2 steerValue = steerAction.action.ReadValue<Vector2>();
        steerInput = steerValue.x;
        accelInput = accelerateAction.action.ReadValue<float>();

        if (carModel != null)
        {
            carModel.position = rb.position;
            carModel.rotation = Quaternion.Slerp(carModel.rotation, rb.rotation, Time.deltaTime * 10f);
        }

        float sidewaysSpeed = Mathf.Abs(Vector3.Dot(rb.linearVelocity, transform.right));
        IsDrifting = sidewaysSpeed > driftThreshold && isGrounded;
        DriftFactor = IsDrifting ? sidewaysSpeed / 10f : 0f;
    }

    private void FixedUpdate()
    {
        CheckGround();
        ApplyAcceleration();
        ApplySteering();
        ApplyDrag();
        ApplyGravity();
    }

    private void CheckGround()
    {
        isGrounded = Physics.Raycast(transform.position, -transform.up, 1.2f);
    }

    private void ApplyAcceleration()
    {
        if (!isGrounded) return;
        if (rb.linearVelocity.magnitude >= maxSpeed) return;

        Vector3 force = transform.forward * accelInput * acceleration;
        rb.AddForce(force, ForceMode.Acceleration);
    }

    private void ApplySteering()
    {
        if (!isGrounded) return;
        if (rb.linearVelocity.magnitude < 1f) return;

        float turnAmount = steerInput * steering * Time.fixedDeltaTime;
        Quaternion turnRotation = Quaternion.Euler(0f, turnAmount, 0f);
        rb.MoveRotation(rb.rotation * turnRotation);
    }

    private void ApplyDrag()
    {
        rb.linearDamping = isGrounded ? groundDrag : airDrag;
    }

    private void ApplyGravity()
    {
        if (!isGrounded)
        {
            rb.AddForce(Vector3.down * gravityForce, ForceMode.Acceleration);
        }
    }
}
Attach the script and set up input actions

The script is written, but Unity needs you to attach it to the right GameObject and configure the input actions it references.

  • In the Hierarchy window, click on your Sphere GameObject (the physics driver with the disabled Mesh Renderer).
  • In the Inspector, click Add Component and search for CarController. Select it to attach your script.
  • In the Car Model field that appears, drag the CarModel GameObject from the Hierarchy into the slot.

Now you need to create an Input Actions asset so the script knows which keys to listen for.

  • In the Project window, right-click inside Assets and select Create > Input Actions.
  • Name it PlayerInputActions and double-click to open the Input Actions editor.
  • In the Action Maps panel on the left, click the + button. Name the new map Player.
  • In the Actions panel, click + to add an action. Name it Steer.
  • With Steer selected, set Action Type to Value and Control Type to Vector 2 in the properties on the right.
  • Under the Steer action, click + next to the binding and select Add Up/Down/Left/Right Composite. Bind Left to the A key and Right to the D key (click each binding row, then press the key to assign it).
  • Click + again in the Actions panel to add a second action. Name it Accelerate.
  • Set Action Type to Value and Control Type to Axis.
  • Add a binding and assign it to the W key.
  • Click Save Asset at the top of the Input Actions editor, then close it.

What is an Input Actions asset?

An Input Actions asset maps physical inputs (keyboard keys, gamepad sticks, touchscreen) to named actions your code references. Your script asks for "Steer" and "Accelerate" without caring whether the input comes from a keyboard or a virtual joystick.

This separation is what makes the same code work on both desktop and mobile later.

  • Back in the Inspector with the Sphere selected, expand the PlayerInputActions asset in the Project window by clicking the arrow next to it. You'll see the Player action map, and inside it the individual actions.
  • Drag the Steer action into the Steer Action field on the CarController component.
  • Drag the Accelerate action into the Accelerate Action field.
  • Press the Play button at the top of the Editor (or press Ctrl+P) to enter Play mode.
  • Press W to accelerate and A/D to steer. Your car should move forward, turn, and the camera should follow it around the track.

Car not moving?

  • Check that CarController is attached to the Sphere GameObject, not the CarModel. The script needs the Rigidbody component, which lives on the Sphere.
  • Verify both Steer Action and Accelerate Action fields are assigned in the Inspector. Empty fields mean no input is being read.
  • Make sure the Sphere is positioned slightly above the road surface (Y position around 1). If it spawns inside the road, the raycast ground check won't work correctly.

Help me figure out why my car isn't moving in Play mode

Your car is alive. It accelerates, steers, and the drift detection is already watching for sideways movement. Next up, you'll build the boost system that rewards the player for drifting.

Implement the Drift-to-Boost System

Your car can now accelerate, steer, and drift around corners. The next question is: what does the player get for taking that risk?

In Burnout games, drifting fills a boost meter. The longer and harder you drift, the more boost you earn. Activating boost gives a burst of speed accompanied by a camera FOV widening and speed particles streaming behind the car. This is the core risk-reward loop that makes the driving feel compelling.

In this step, get ready to:
  • Create a BoostSystem script that fills a meter while drifting.
  • Display the boost meter with a UI Slider and activate boost on button press.
  • Add camera FOV widening and speed particles for satisfying boost feedback.
Create the BoostSystem script

The BoostSystem handles three responsibilities: filling the meter when the car drifts, draining it when the player activates boost, and driving visual feedback (FOV changes and particles).

  • In the Assets folder in the Project window, right-click and select Create > C# Script.
  • Name the script BoostSystem.
  • Double-click BoostSystem.cs to open it in Visual Studio.
  • Replace the default contents with the following code:
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class BoostSystem : MonoBehaviour
{
    [Header("Boost Settings")]
    public float fillRate = 0.5f;
    public float drainRate = 0.8f;
    public float boostMultiplier = 1.5f;

    [Header("References")]
    public CarController carController;
    public Slider boostSlider;
    public InputActionReference boostAction;
    public Camera mainCamera;
    public ParticleSystem boostParticles;

    [Header("Camera Juice")]
    public float normalFOV = 60f;
    public float boostFOV = 75f;
    public float fovLerpSpeed = 5f;

    private float boostMeter;
    public bool IsBoosting { get; private set; }

    private void OnEnable()
    {
        boostAction.action.Enable();
    }

    private void OnDisable()
    {
        boostAction.action.Disable();
    }

    private void Update()
    {
        // Fill the meter while drifting (only when not already boosting)
        if (carController.IsDrifting && !IsBoosting)
        {
            boostMeter += carController.DriftFactor * fillRate * Time.deltaTime;
        }

        // Check if the player is pressing the boost button
        bool boostPressed = boostAction.action.IsPressed();
        IsBoosting = boostPressed && boostMeter > 0f;

        if (IsBoosting)
        {
            // Drain the meter while boosting
            boostMeter -= drainRate * Time.deltaTime;

            // Start speed particles if not already playing
            if (boostParticles != null && !boostParticles.isPlaying)
            {
                boostParticles.Play();
            }
        }
        else
        {
            // Stop particles when not boosting
            if (boostParticles != null && boostParticles.isPlaying)
            {
                boostParticles.Stop();
            }
        }

        // Keep meter between 0 and 1
        boostMeter = Mathf.Clamp01(boostMeter);

        // Update the UI slider to show current meter value
        if (boostSlider != null)
        {
            boostSlider.value = boostMeter;
        }

        // Lerp camera FOV for speed sensation
        float targetFOV = IsBoosting ? boostFOV : normalFOV;
        mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOfView, targetFOV, fovLerpSpeed * Time.deltaTime);
    }

    // Returns a force multiplier other scripts can use
    public float GetBoostForceMultiplier()
    {
        return IsBoosting ? boostMultiplier : 1f;
    }

    // Allows external scripts to add boost (used for near-miss bonus)
    public void AddBoost(float amount)
    {
        boostMeter = Mathf.Clamp01(boostMeter + amount);
    }
}

What does this code do?

The script has three main sections working together in Update():

  • Meter fill: when CarController.IsDrifting is true, the meter increases based on DriftFactor (how hard the car is sliding). Harder drifts fill faster.
  • Boost activation: when the player holds the boost button and the meter is above zero, IsBoosting becomes true. The meter drains while boosting.
  • Visual feedback: the camera FOV lerps from 60 to 75 degrees during boost (creating a speed tunnel effect), and a particle system plays behind the car.
  • GetBoostForceMultiplier() and AddBoost() are public methods that other scripts can call to integrate with the boost system.
  • Save BoostSystem.cs and switch back to the Unity Editor.
  • Wait for the script to compile. You should see no errors in the Console window at the bottom.

Seeing a compilation error?

  • If you see an error about UnityEngine.UI not being found, make sure the com.unity.ugui package is installed. Go to Window > Package Manager and check that Unity UI is listed.
  • If you see an error about InputActionReference, confirm that the Input System package is installed from the previous step.

Still stuck? Help me fix a compilation error in BoostSystem.cs

✔️ Awesome, I've got everything!

Great. Make sure you have saved the file before moving on.

ⓧ I'd like to double check the full code

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class BoostSystem : MonoBehaviour
{
    [Header("Boost Settings")]
    public float fillRate = 0.5f;
    public float drainRate = 0.8f;
    public float boostMultiplier = 1.5f;

    [Header("References")]
    public CarController carController;
    public Slider boostSlider;
    public InputActionReference boostAction;
    public Camera mainCamera;
    public ParticleSystem boostParticles;

    [Header("Camera Juice")]
    public float normalFOV = 60f;
    public float boostFOV = 75f;
    public float fovLerpSpeed = 5f;

    private float boostMeter;
    public bool IsBoosting { get; private set; }

    private void OnEnable()
    {
        boostAction.action.Enable();
    }

    private void OnDisable()
    {
        boostAction.action.Disable();
    }

    private void Update()
    {
        if (carController.IsDrifting && !IsBoosting)
        {
            boostMeter += carController.DriftFactor * fillRate * Time.deltaTime;
        }

        bool boostPressed = boostAction.action.IsPressed();
        IsBoosting = boostPressed && boostMeter > 0f;

        if (IsBoosting)
        {
            boostMeter -= drainRate * Time.deltaTime;

            if (boostParticles != null && !boostParticles.isPlaying)
            {
                boostParticles.Play();
            }
        }
        else
        {
            if (boostParticles != null && boostParticles.isPlaying)
            {
                boostParticles.Stop();
            }
        }

        boostMeter = Mathf.Clamp01(boostMeter);

        if (boostSlider != null)
        {
            boostSlider.value = boostMeter;
        }

        float targetFOV = IsBoosting ? boostFOV : normalFOV;
        mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOfView, targetFOV, fovLerpSpeed * Time.deltaTime);
    }

    public float GetBoostForceMultiplier()
    {
        return IsBoosting ? boostMultiplier : 1f;
    }

    public void AddBoost(float amount)
    {
        boostMeter = Mathf.Clamp01(boostMeter + amount);
    }
}
Set up the boost UI and input action

The boost meter needs a visible bar on screen so the player knows how much boost they have stored. You also need an input action for the boost button.

  • In the Unity menu bar, click GameObject > UI > Slider.
  • Unity automatically creates a Canvas (set to Screen Space - Overlay) and an EventSystem if they do not exist yet.
  • Select the new Slider in the Hierarchy.
  • In the Inspector, set Min Value to 0 and Max Value to 1.
  • Uncheck Interactable so the player cannot drag the slider manually.
  • Use the Rect Transform to position the slider at the bottom of the screen. Set the anchor to bottom-center and adjust the width to around 300 and height to 20.

Why a UI Slider for the boost meter?

The UnityEngine.UI.Slider component has a value property that maps directly to a 0-1 range. Your BoostSystem sets boostSlider.value = boostMeter each frame, and the Slider visually fills to match. No custom rendering code needed.

Now add the Boost action to your Input Actions asset:

  • Open your Input Actions asset (the one you created in the previous step with Steer and Accelerate actions).
  • In the Player action map, click the + button to add a new action.
  • Name it Boost and set its Action Type to Button.
  • Add a binding. Set it to Keyboard > Left Shift for testing in the Editor.
  • Click Save Asset in the Input Actions editor.

Now attach the script and wire the references:

  • Select the Sphere GameObject (your physics driver) in the Hierarchy.
  • Click Add Component in the Inspector and search for BoostSystem. Add it.
  • Drag the Sphere's CarController component into the Car Controller field.
  • Drag the Slider from the Hierarchy into the Boost Slider field.
  • Drag the Boost action reference from your Input Actions asset into the Boost Action field.
  • Drag the Main Camera from the Hierarchy into the Main Camera field.
  • Press Play to enter Play mode.
  • Drive the car and steer hard into a turn to drift. You should see the Slider at the bottom filling up as you slide.
  • Hold Left Shift while the meter has charge. The camera should widen slightly (FOV increases) and the meter drains.

Slider not filling when you drift?

  • Confirm the Car Controller reference is assigned in the Inspector. Without it, the script cannot read IsDrifting.
  • Make sure you are actually drifting. The car needs sideways speed above the driftThreshold value (2 by default). Steer sharply at speed.
  • Check that the Slider's Max Value is set to 1, not 100.

Still stuck? Help me debug why my boost meter isn't filling when I drift

Add the boost particle effect

The FOV change already sells the sensation of speed. Adding stretched particles streaming behind the car completes the visual feedback loop.

  • In the Hierarchy, right-click and select Effects > Particle System.
  • Rename it BoostParticles.
  • Parent it to the CarModel GameObject by dragging it onto CarModel in the Hierarchy.
  • Position it behind the car body. Set Position to approximately (0, 0, -1.5) so particles emit from behind.
  • Set Rotation to (0, 180, 0) so particles shoot backward.

Now configure the particle system to look like speed streaks:

  • In the Particle System main module, set Start Lifetime to 0.3.
  • Set Start Speed to 20.
  • Set Start Size to 0.1.
  • Under Emission, set Rate over Time to 50.
  • Expand the Renderer module. Change Render Mode to Stretched Billboard.
  • Set Length Scale to 5 so each particle looks like a long speed streak.
  • Uncheck Play On Awake so the particles only play when the script calls Play().

Why Stretched Billboard for speed particles?

Stretched Billboard mode elongates each particle along its velocity direction. Combined with a high Length Scale, short-lived particles look like motion blur streaks. This is the same technique racing games use to sell speed without expensive post-processing effects.

  • Select the Sphere in the Hierarchy. In the BoostSystem component, drag BoostParticles from the Hierarchy into the Boost Particles field.
  • Press Play to enter Play mode.
  • Drift to fill the meter, then hold Left Shift. You should see speed streaks shooting from behind the car and the camera FOV widening.
  • Release Left Shift. The particles stop and the FOV smoothly returns to normal.

Particles not appearing during boost?

  • Check that Play On Awake is unchecked on the Particle System. If it is checked, particles play immediately and the script's Play() call has no visible effect.
  • Confirm the Boost Particles field is assigned in the Inspector. A missing reference means the null check skips the play/stop calls.
  • If particles appear but face the wrong direction, adjust the BoostParticles Y rotation to 180 degrees.

Still stuck? Help me fix my boost particles in Unity

Your car now has the complete Burnout-style loop: drift to fill, boost to burn. Next up, you will add on-screen touch controls so this works on a mobile device.

Add Mobile Touch Controls

Your car now drifts, fills a boost meter, and triggers satisfying camera effects when you activate boost. All of that works with keyboard input in the Editor, but mobile players need something they can touch.

On-screen controls translate finger touches into the same gamepad signals your scripts already read. In this step, you will create a formal Input Actions asset, add a virtual joystick and boost button to your Canvas, and wire everything together so the game is playable on a phone.

In this step, get ready to:
  • Create an Input Actions asset with a Player action map.
  • Add on-screen touch controls (joystick and boost button) to your UI Canvas.
  • Wire the Input Action References so steering, acceleration, and boost respond to touch.
Create the Input Actions asset

An Input Actions asset is a file that maps named actions (like "Steer" or "Boost") to device controls (like a gamepad stick or button). Your scripts reference these actions instead of hard-coding specific keys, so the same code works on keyboard, gamepad, and touch.

  • First, verify your Input System backend is set correctly. Go to Edit > Project Settings > Player.
  • Find the Active Input Handling dropdown under Other Settings > Configuration.
  • Set it to Both. This enables the new Input System while keeping the legacy input available for testing.

Why Both instead of just New?

Selecting Both keeps the legacy Input Manager active alongside the new Input System. This means keyboard shortcuts in the Editor (like Play/Stop) keep working while your touch controls use the new system.

  • Unity may ask to restart the Editor. Click Apply and let it restart if prompted.
  • Once back in the Editor, right-click in the Project window (the Assets panel at the bottom).
  • Select Create > Input Actions.
  • Name the new asset PlayerInputActions.
  • Double-click PlayerInputActions to open the Input Actions Editor.

Now create the action map and its actions:

  • In the Action Maps panel on the left, click the + icon to add a new action map.
  • Name it Player.
  • In the Actions column, click the + icon to add a new action. Name it Steer.
  • In the Properties panel on the right, set Action Type to Value and Control Type to Vector 2.
  • Expand the Steer action's binding. Click the Path dropdown and search for Left Stick [Gamepad]. Select it so the binding reads <Gamepad>/leftStick.
  • Add a second action named Accelerate. Set its Action Type to Value and Control Type to Axis.
  • Bind Accelerate to <Gamepad>/leftTrigger.
  • Add a third action named Boost. Set its Action Type to Button.
  • Bind Boost to <Gamepad>/buttonSouth.
  • Press Ctrl+S (Windows) or Cmd+S (macOS) to save the asset.

What is an action map?

An action map groups related inputs for one context. A "Player" map holds driving controls, while a "UI" map might hold menu navigation. You can enable or disable entire maps at once to switch between gameplay and menus.

  • Confirm you see three actions (Steer, Accelerate, Boost) listed under the Player action map in the editor.

Don't see the Input Actions option in the Create menu?

This means the Input System package is not installed. Go to Window > Package Manager, search for "Input System", and click Install. After installation, return to the Project window and try again.

Help me troubleshoot the Input System package installation.

Set up the on-screen joystick and boost button

On-screen controls are UI elements that simulate gamepad input when touched. The OnScreenStick component translates finger drags into a virtual left stick. The OnScreenButton component sends a button press when tapped.

  • In the Hierarchy, expand your existing Canvas (the one that already holds the boost Slider).
  • Right-click the Canvas and select UI > Image. Rename it StickArea.
  • In the Rect Transform, anchor it to the bottom-left of the screen. Set Width and Height to 150.
  • Assign a circular sprite to the Source Image field in the Image component. Set Color alpha to around 0.5 so it is translucent.
  • With StickArea selected, click Add Component in the Inspector.
  • Search for On-Screen Stick and add it.
  • In the On Screen Stick component, click the Control Path field. Select Left Stick [Gamepad] so the path reads <Gamepad>/leftStick.

How does OnScreenStick work?

When a player drags their finger on the stick image, the component creates a virtual gamepad device and writes the drag position to its left stick. Your CarController reads steerAction.action.ReadValue<Vector2>() which picks up this virtual stick input exactly as if a real gamepad were connected.

Now add the boost button:

  • Right-click the Canvas again and select UI > Button. Rename it BoostButton.
  • Anchor it to the bottom-right of the screen. Set Width and Height to 120.
  • Assign a circular sprite to the button's Image component. Change the child Text to say BOOST.
  • With BoostButton selected, click Add Component.
  • Search for On-Screen Button and add it.
  • In the On Screen Button component, set Control Path to Button South [Gamepad] so the path reads <Gamepad>/buttonSouth.
  • Save your scene with Ctrl+S (Windows) or Cmd+S (macOS).
  • In the Game view, you should now see a translucent circle in the bottom-left (the joystick) and a boost circle in the bottom-right.

Controls not visible in the Game view?

Make sure both StickArea and BoostButton are children of the Canvas. If they sit outside the Canvas hierarchy, they will not render on screen.

Also check the anchors. If anchored to center instead of a corner, they may be hidden behind the 3D viewport. Re-anchor to bottom-left or bottom-right.

Help me figure out why my on-screen controls are not showing up.

Wire the Input Action References in the Inspector

Your scripts already use InputActionReference fields to read input. The last step is connecting those fields to the actions you just created, so the on-screen controls feed data into the car controller and boost system.

  • In the Hierarchy, select the Sphere (the physics driver with CarController attached).
  • In the Inspector, find the Car Controller component's References section.
  • Drag your PlayerInputActions asset from the Project window into the Steer Action field. From the dropdown, select Player/Steer.
  • Do the same for Accelerate Action, selecting Player/Accelerate.
  • Now find the Boost System component on the same GameObject.
  • Set the Boost Action field to Player/Boost.

What does this wiring do?

When the player touches the on-screen stick, the OnScreenStick component writes values to a virtual <Gamepad>/leftStick. Because your Steer action is bound to that same path, steerAction.action.ReadValue<Vector2>() receives the touch data. The same pattern connects the boost button to boostAction.action.IsPressed().

  • Press Play in the Editor toolbar.
  • Click and drag on the joystick area in the Game view. Your car should steer in response.
  • Click the boost button while the meter has charge. The camera FOV should widen and particles should appear.

Test touch input without a phone

The on-screen controls respond to mouse clicks in the Editor, which simulates touch. You can also install the Unity Remote 5 app from the Play Store to stream input from your phone directly to the Editor for a more realistic test.

Car not responding to the joystick?

Double-check that the Steer Action and Accelerate Action fields in the CarController Inspector are assigned. If they show "None", the script cannot read any input.

Also verify that Active Input Handling is set to Both in Player Settings. If it is set to the old input only, the new Input System actions will not fire.

Help me debug why my car doesn't respond to on-screen joystick input.

Your car now responds to touch input. In the next step, you will configure the project for a mobile build and optimize performance for 60fps on a phone.

Configure the Mobile Build

Your on-screen touch controls are wired up and the car responds beautifully in the Editor. The final challenge is getting this game running on a real phone.

Mobile hardware is far more constrained than your development PC. Unity can build directly to Android devices, but you need to configure the platform, strip rendering overhead, and lock the frame rate to keep everything buttery smooth at 60fps.

In this step, get ready to:
  • Switch the build platform to Android and configure Player Settings.
  • Create a mobile-optimized quality level and reduce rendering overhead.
  • Test on a connected Android device or Unity Remote 5.
Switch the build platform to Android

Unity 6 uses Build Profiles to manage platform targets. You need to create an Android profile so Unity recompiles assets and scripts for mobile hardware.

  • In the Unity Editor, click File in the top menu bar.
  • Select Build Profiles.
  • In the Build Profiles window, click Add Build Profile.
  • Select Android from the Platform Browser, then click Add Build Profile.
  • Select the new Android profile in the list and click Switch Profile.

What does switching profile do?

Unity reimports all assets and recompiles scripts for the Android platform. This can take a minute or two depending on your project size. You will see a progress bar at the bottom of the Editor.

Once the platform switch completes, you need to configure Player Settings for your Android build.

  • Go to Edit > Project Settings.
  • Select the Player category in the left sidebar.
  • Click the Android tab (the Android icon).
  • Set Company Name to your name or studio name (e.g. NextWorkGames).
  • Set Product Name to BurnoutDrift.
  • Expand the Other Settings section.
  • Find Minimum API Level and set it to Android 7.0 'Nougat' (API Level 24).
  • Scroll up to Graphics APIs (still in Other Settings). Uncheck Auto Graphics API.
  • Ensure Vulkan is listed first, followed by OpenGLES3. If OpenGLES3 is missing, click the + button to add it.

Why Vulkan and OpenGLES3?

Vulkan is the modern graphics API for Android with better performance on newer devices. OpenGLES3 acts as a fallback for older phones that do not support Vulkan. Listing both ensures your game runs on the widest range of hardware.

Don't see the Android tab?

If the Android icon is grayed out or missing, you may not have installed the Android Build Support module. Return to Unity Hub, go to Installs, click the gear icon on your Unity 6.3 install, select Add Modules, and check Android Build Support.

help me fix the missing Android platform in Unity

Optimize for mobile performance

Mobile GPUs have tight thermal and power budgets. Disabling expensive features like real-time shadows and reducing quality settings keeps your frame time under 16ms for a stable 60fps.

  • Go to Edit > Project Settings > Quality.
  • In the Levels list, select any existing quality level to highlight it.
  • Click the Add Quality Level button to create a duplicate.
  • Rename the new level to Mobile.
  • With Mobile selected, set Shadows to Disable Shadows.
  • Set Anti Aliasing to 2x Multi Sampling.
  • Set VSync Count to Don't Sync.
  • Set the Mobile level as the default for Android by clicking the green checkmark column next to the Android icon.

Why disable VSync on mobile?

VSync ties your frame rate to the display refresh rate, but mobile screens vary wildly (60Hz, 90Hz, 120Hz). Using Application.targetFrameRate gives you consistent 60fps regardless of the screen hardware.

Now you need a small startup script that locks the frame rate to 60fps when the game launches.

  • In the Project window, right-click inside your Scripts folder.
  • Select Create > C# Script.
  • Name it GameStartup.
  • Double-click GameStartup.cs to open it in Visual Studio, then replace all the contents with the following code:
using UnityEngine;

public class GameStartup : MonoBehaviour
{
    // Lock the frame rate to 60fps on mobile devices
    private void Awake()
    {
        Application.targetFrameRate = 60;
    }
}

What does this code do?

The Awake() method runs once when the GameObject is first loaded. Setting Application.targetFrameRate = 60 tells Unity to aim for 60 frames per second. This is more reliable than VSync on mobile because it works consistently across different display hardware.

  • Save GameStartup.cs and switch back to the Unity Editor.
  • Create an empty GameObject in your scene (right-click in Hierarchy > Create Empty).
  • Rename it to GameManager.
  • Drag GameStartup.cs onto the GameManager GameObject to attach it.

Script not showing in the Inspector?

Make sure the class name inside the script matches the file name exactly. The file must be GameStartup.cs and the class must be public class GameStartup. Unity will show a compile error in the Console if there is a mismatch.

help me fix my GameStartup script not attaching

Finally, reduce the URP rendering overhead for mobile.

  • In the Project window, search for URP to find your URP Asset (it will be a file with a pipeline icon).
  • Click on the URP Asset to open it in the Inspector.
  • Under the Shadows section, set Max Distance to 20.
  • Under the Lighting section, uncheck Additional Lights to disable them.

Why reduce shadow distance?

Shadow distance controls how far from the camera Unity renders real-time shadows. On mobile, a short shadow distance (20 units) keeps shadows visible near the car without wasting GPU time on shadows the player cannot even see in the distance.

Test on a connected Android device

The fastest way to test touch controls without doing a full APK build is Unity Remote 5. This app streams your Editor's Game view to your phone and sends touch input back.

  • On your Android phone, open the Google Play Store and install Unity Remote 5.
  • Enable USB Debugging on your phone (Settings > Developer Options > USB Debugging).
  • Connect your phone to your PC with a USB data cable.
  • In Unity, go to Edit > Project Settings > Editor.
  • Under Unity Remote, set the Device dropdown to Any Android Device.
  • Open the Unity Remote 5 app on your phone.
  • Press Play in the Unity Editor.

Your phone should mirror the Game view. Touch the on-screen joystick and boost button to verify the car responds. The car should accelerate, steer, and drift at a smooth 60fps.

No Android phone?

You can still verify your build settings by doing a full Build and Run. Go to File > Build Profiles, select your Android profile, and click Build and Run with a phone connected via USB. Unity will install the APK and launch it automatically.

Phone not detected by Unity Remote?

Make sure you opened the Unity Remote 5 app on your phone before pressing Play in Unity. Also confirm USB Debugging is enabled and that you accepted the "Allow USB debugging" prompt on the phone.

Try a different USB cable. Some cables are charge-only and do not transfer data.

help me connect Unity Remote 5 to my phone

✔️ Awesome, I've got everything!

Great. Double check you have saved all your files and that your Quality Settings show the Mobile level as default for Android.

ⓧ I'd like to double check the full code

Here is the GameStartup.cs script in full:

using UnityEngine;

public class GameStartup : MonoBehaviour
{
    // Lock the frame rate to 60fps on mobile devices
    private void Awake()
    {
        Application.targetFrameRate = 60;
    }
}

Secret mission

Near-Miss Boost Bonus

Real racing games reward risky driving. In Burnout Paradise, threading through traffic at high speed fills your boost even faster. Your mission: add AI traffic cars to the track and reward the player with bonus boost when they narrowly dodge a collision.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally using the free Unity Personal license, so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • BurnoutDrift Unity project folder (local files, scripts, scenes, assets).
  • Unity 6.3 LTS Editor (installed via Unity Hub).
  • Unity Hub (application for managing Unity installs and projects).
  • Visual Studio (installed alongside Unity for C# scripting).

Keep everything running

No action needed. Choose this if you are still actively building or want to keep iterating on your racing prototype.

  • Your BurnoutDrift project stays in place wherever Unity Hub saved it.
  • Unity Hub, Unity 6.3 LTS, and Visual Studio remain installed and ready to use.
  • You can reopen the project any time from Unity Hub's Projects list.

Pause - I'll come back to this later

Close running applications to free up memory. Your project files and installed tools stay in place for when you return.

  • Close the Unity Editor by clicking File then Exit.
  • Close Visual Studio if it is open.
  • Optionally close Unity Hub from the system tray to free additional memory.
  • When you are ready to return, open Unity Hub and select your BurnoutDrift project from the Projects list.

Delete - I don't want to use this again

Remove all project files and optionally uninstall the tools. This frees up significant disk space (Unity Editor alone is several GB).

  • Delete the BurnoutDrift project folder. Open File Explorer, find the BurnoutDrift folder (check Unity Hub's Projects list for the exact path), right-click it, and select Delete.
  • Remove the Unity 6.3 LTS Editor. Open Unity Hub, click the Installs tab, click Manage next to the Unity 6.3 LTS entry, select Uninstall, and confirm.
  • Uninstall Unity Hub. Open Windows Settings, go to Apps, then Installed apps. Search for Unity Hub, click the three-dot menu, and select Uninstall.
  • Uninstall Visual Studio. In the same Installed apps list, search for Visual Studio, click the three-dot menu, and select Uninstall. Follow the Visual Studio Installer prompts to complete removal.

That's a Wrap!

That's a Wrap!

Nice work! You just built an arcade racing prototype with the core "feel" of Burnout.

You've learned how to:

  • Built a sphere-based arcade car controller with drift detection, responsive steering, and dynamic drag for satisfying Rigidbody physics.
  • Implemented a drift-to-boost mechanic with camera FOV widening and speed particles that sell the sensation of velocity.
  • Set up mobile touch controls using Unity's Input System with OnScreenStick and OnScreenButton, and configured an Android build optimized for 60fps gameplay.
  • Secret Mission: Added AI traffic cars with a near-miss boost bonus and dramatic slowmo effect for high-risk, high-reward gameplay.

Ready to quiz yourself?