Complete C# Unity Game Developer 2D - Delivery Driver

Hello,

I was going through the Delivery Driver section for a second time, and I wanted to try and make it more interesting. I thought “I could add cars as obstacles on the road, but moving by themselves.” I added waypoints and got help implementing the code for that…my question is how can I make the vehicles behave more like real cars? They float around like hovercraft. It still makes for good obstacles, but it would be better if they steered. Here is my code for car movement, I would appreciate any suggestions to implement steering in the non-player controlled cars.

‘’’ using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CarMovement : MonoBehaviour
{

[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float arrivalThreshold = 0.1f;
[SerializeField] private Transform waypointsContainer;

private Transform[] waypoints;
private int currentWaypointIndex = 0;
private Rigidbody2D rb;
public Transform[] wheelVisuals;
public WheelCollider[] wheelColliders;

void Start()
{
    waypoints = new Transform[waypointsContainer.childCount];
    for (int i = 0; i < waypointsContainer.childCount; i++)
    {
        waypoints[i] = waypointsContainer.GetChild(i);
    }

    // Initialize the Rigidbody
    rb = GetComponent<Rigidbody2D>();
    rb.gravityScale = 0f; // Disable gravity for the car

    // Check if the arrays have the same length
    if (wheelVisuals.Length != wheelColliders.Length)
    {
        Debug.LogError("The number of wheel visual transforms doesn't match the number of wheel colliders.");
        return;
    }

    // Assign visual wheel transforms to the Wheel Colliders
    for (int i = 0; i < wheelColliders.Length; i++)
    {
        WheelCollider wheelCollider = wheelColliders[i];
        Transform wheelVisual = wheelVisuals[i];

        // Check if both the Wheel Collider and visual transform are assigned
        if (wheelCollider != null && wheelVisual != null)
        {
            wheelCollider.center = wheelVisual.localPosition;
        }
        else
        {
            Debug.LogError("One or more wheel colliders or visual transforms are not assigned.");
        }
    }
}

void Update()
{
    MoveToNextWaypoint();

   
    // Calculate the direction to the next waypoint
    Vector3 directionToWaypoint = waypoints[currentWaypointIndex].position - transform.position;

    // Calculate the desired steering angle based on the direction
    float desiredSteeringAngle = Vector3.SignedAngle(transform.forward, directionToWaypoint, transform.up);

    // Apply the desired steering angle to the front wheel colliders
    wheelColliders[0].steerAngle = desiredSteeringAngle;
    wheelColliders[1].steerAngle = desiredSteeringAngle;

    // Gradually adjust the steering angle
    float steeringSpeed = 5f; // Adjust as needed
    float currentSteeringAngle = wheelColliders[0].steerAngle;
    wheelColliders[0].steerAngle = Mathf.Lerp(currentSteeringAngle, desiredSteeringAngle, Time.deltaTime * steeringSpeed);
    wheelColliders[1].steerAngle = Mathf.Lerp(currentSteeringAngle, desiredSteeringAngle, Time.deltaTime * steeringSpeed);

    if (wheelColliders.Length > 0)
    {
        // Access the first element in the wheelColliders array
        wheelColliders[0].steerAngle = desiredSteeringAngle;
    }

    if (waypoints.Length > 0 && currentWaypointIndex < waypoints.Length)
    {
        // Access the waypoint at the current index
        Vector3 targetDirection = waypoints[currentWaypointIndex].position - transform.position;
        // Calculate desired steering angle based on directionToWaypoint
        // ...
    }

}

void MoveToNextWaypoint()
{
    // Check if the car reached the current waypoint
    if (Vector2.Distance(transform.position, waypoints[currentWaypointIndex].position) <= arrivalThreshold)
    {
        currentWaypointIndex++;

        // Loop back to the first waypoint if all waypoints have been visited
        if (currentWaypointIndex >= waypoints.Length)
        {
            currentWaypointIndex = 0;
        }
    }

    // Calculate the direction to the current waypoint
    Vector2 direction = (waypoints[currentWaypointIndex].position - transform.position).normalized;

    // Apply a force to move the car towards the waypoint
    rb.velocity = direction * moveSpeed;
    }
}   

‘’’

Hi hhatton93,

That’s an interesting idea. :slight_smile:

The reason for that is very likely the friction of the ground. By default, the friction is 0f, which means that everything on the ground behaves like on ice.

You could test a PhysicsMaterial2D on the ground with a higher friction.

Did this help? :slight_smile:


See also:

1 Like

You should be able to find resources online about AI steering. I’m not quite sure what you are seeing and what you expect to see, but I know of one method that may help;

What you would do is to have an empty game object for each car. This game object is the one that follows the waypoints. The car, in turn, tries to follow this empty game object. You would then give the car a follow distance. The closer it is to the empty object, the sharper it’s turns would be and a greater following distance would cause it to arc around turns. It’s then just a matter of fine-tuning the follow distance.

I’ll give it a try, thanks.

very interesting.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms