Unity Car Steering by Itself

Viewed 466

I have a simple car game with a straight road. However, some parts of the road have some corners and I want My car to steer its wheels through those points. I have created some nodes for my car to steer. But my car continues to go straight. I can't figure out where is the problem.

My car and the road

Here is the code for creating the node system:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PathFollower : MonoBehaviour
{

public Color lineColor;

private List<Transform> nodes = new List<Transform>();

private void OnDrawGizmos()
{
    Gizmos.color = lineColor;

    Transform[] pathTransform = GetComponentsInChildren<Transform>();
    nodes = new List<Transform>();

    for(int i = 0; i < pathTransform.Length; i++)
    {
        if (pathTransform[i] != transform)
        {
            nodes.Add(pathTransform[i]);
        }
    }

    for (int i = 0; i < nodes.Count; i++)
    {
        Vector3 previousNode;
        Vector3 currentNode = nodes[i].position;

        if (!(i - 1 < 0))
        {
            previousNode = nodes[i - 1].position;
        }
        else
        {
            previousNode = nodes[0].position;
        }

        Gizmos.DrawLine(previousNode, currentNode);
        Gizmos.DrawWireSphere(currentNode, 0.3f);

    }
}

This script is for my car to steer itself:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AutoSteering : MonoBehaviour
{

public Transform path;
public float maxSteeringAngle = 30f;
public CarPhysic getAxleInfos;

private List<Transform> nodes;
private int currentNode = 0;

void Start()
{
    Transform[] pathTransform = path.GetComponentsInChildren<Transform>();
    nodes = new List<Transform>();

    for (int i = 0; i < pathTransform.Length; i++)
    {
        if (pathTransform[i] != path.transform)
        {
            nodes.Add(pathTransform[i]);
        }
    }
}

private void FixedUpdate()
{
    ApplySteer();
    CheckWaypointDistance();

}

private void ApplySteer()
{
    Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position);
    float newSteer = (relativeVector.x / relativeVector.magnitude) * maxSteeringAngle;

    foreach (AxleInfo axleInfo in getAxleInfos.axleInfos)
    {
        newSteer = axleInfo.leftWheel.steerAngle;
        newSteer = axleInfo.rightWheel.steerAngle;
    }
}

private void CheckWaypointDistance()
{
    if(Vector3.Distance(transform.position, nodes[currentNode].position) < 0.5f)
    {
        if (currentNode == nodes.Count - 1)
        {
            currentNode = 0;
        }
        else
        {
            currentNode++;
        }
    }
}

This one is for the car physic that I've copied some parts from unity tutorial itself:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;


[System.Serializable]
public class AxleInfo
{
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor;
    public bool newSteer;
}

public class CarPhysic : MonoBehaviour
{
    public List<AxleInfo> axleInfos;
    public float maxMotorTorque;
    public float brake;
    public bool isBraking;
    public Transform carPosition;
    public float mudForce = 300f;
    public Canvas myCanvas;


private Rigidbody rigidbody;


public void ApplyLocalPositionToVisuals(WheelCollider collider)
{
    if (collider.transform.childCount == 0)
    {
        return;
    }

    Transform visualWheel = collider.transform.GetChild(0);

    Vector3 position;
    Quaternion rotation;
    collider.GetWorldPose(out position, out rotation);

    visualWheel.transform.position = position;
    visualWheel.transform.rotation = rotation;
}

private void Braking(AxleInfo axleInfo)
{
    if (isBraking)
    {
        axleInfo.leftWheel.brakeTorque = brake;
        axleInfo.rightWheel.brakeTorque = brake;
    }
    else
    {
        axleInfo.leftWheel.brakeTorque = 0;
        axleInfo.rightWheel.brakeTorque = 0;  
    } 
}

void Start()
{
    rigidbody = GetComponent<Rigidbody>();
}

public void FixedUpdate()
{
    float motor = maxMotorTorque * Input.GetAxis("Vertical");

    foreach (AxleInfo axleInfo in axleInfos)
    {
        if (axleInfo.motor)
        {
            isBraking = false;
            axleInfo.leftWheel.motorTorque = motor;
            axleInfo.rightWheel.motorTorque = motor;
        }
        if (Input.GetKey(KeyCode.Space))
        {
            isBraking = true;
            Braking(axleInfo);
        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            isBraking = false;
            axleInfo.leftWheel.brakeTorque = 0;
            axleInfo.rightWheel.brakeTorque = 0;
        }
        ApplyLocalPositionToVisuals(axleInfo.leftWheel);
        ApplyLocalPositionToVisuals(axleInfo.rightWheel);
    }
}
private void Update()
{
    RaycastHit hit;

    if (Physics.Raycast(carPosition.position, transform.TransformDirection(Vector3.down * 100), out hit))
    {
        Debug.DrawRay(carPosition.position, Vector3.down * 100, Color.red);

        if (hit.collider.gameObject.tag == "mud")
        {
            Debug.Log("done");
            rigidbody.AddForce(Vector3.right * mudForce, ForceMode.Impulse);
        }

        if (hit.collider.gameObject.tag == "FinishPoint")
        {
            myCanvas.gameObject.SetActive(true);
            foreach(AxleInfo axleInfo in axleInfos)
            {
                isBraking = true;
                maxMotorTorque = 0;
                Braking(axleInfo);
            }
        }
    }
}
1 Answers

Without looking at the rest of your code in ApplySteer you do

private void ApplySteer()
{
    Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position);
    float newSteer = (relativeVector.x / relativeVector.magnitude) * maxSteeringAngle;

    foreach (AxleInfo axleInfo in getAxleInfos.axleInfos)
    {
        newSteer = axleInfo.leftWheel.steerAngle;
        newSteer = axleInfo.rightWheel.steerAngle;
    }
}

where you store some values into newSteer in a loop. So anyway you would only store the last value. And then you never use that value.

I guess - I'm pretty sure - what you rather wanted to do would be

private void ApplySteer()
{
    Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position);
    float newSteer = (relativeVector.x / relativeVector.magnitude) * maxSteeringAngle;

    foreach (AxleInfo axleInfo in getAxleInfos.axleInfos)
    {
        axleInfo.leftWheel.steerAngle = newSteer;
        axleInfo.rightWheel.steerAngle = newSteer;
    }
}
Related