1
\$\begingroup\$

I am using Ackermann steering to rotate a vehicle. The code is as follows:

    if (turningLeft || turningRight) {
        // Rotate around a dummy pivot point
        float turnDir = turningLeft ? -1 : 1;
        Vector3 turningPivotPoint = 
            dummyPivot.transform.TransformPoint(
                new Vector3(turningCenterDistance * turnDir, 0, 0));
        dummyPivot.transform.RotateAround(
                    turningPivotPoint, 
                    Vector3.up * gasDir * turnDir, 
                    angleVel * Time.deltaTime);
    }

    // The player is pressing the gas
    if (isGas) {
        angleVel = Mathf.Lerp (angleVel, maxAngleVel,Time.deltaTime);
    }

    if (angleVel == 0) {
        turningLeft = turningRight = false;
    }

    gasVel = Mathf.Lerp(gasVel, angleVel * Mathf.Deg2Rad * turningCenterDistance, Time.deltaTime);

    dummyPivot.transform.position = 
        dummyPivot.transform.position + dummyPivot.transform.forward * Time.deltaTime * gasVel * gasDir;

The issue is that the speed of the vehicle when it is turning does not match its speed when driving straight. Driving the vehicle in circles will be slower than driving the vehicle forward.

How do I fix this?

\$\endgroup\$
1
\$\begingroup\$
using UnityEngine;
using System.Collections;

public class CarController : MonoBehaviour
{
    int turn = 0;
    float acceleration = 0;
    float speed = 0;
    public float friction = 0.98f; //feel free to fiddle with this

    void Update ()
    {
        turn = 0;
        acceleration = 0;
        speed *= friction; //dampen

        turn += Input.GetKey("a") ? -1 : 0;
        turn += Input.GetKey("d") ? +1 : 0;

        acceleration += Input.GetKey("w") ? 0.2f * Time.deltaTime : 0;
        speed += acceleration;

        transform.Rotate(0, turn, 0);
        transform.Translate(Vector3.forward * speed , Space.Self); //look up what Space.Self does!
    }
}

You can see that our position is always updated by adding Vector3.forward * speed. This means we will always have the same linear velocity regardless of whether or not we are turning, provided the speed, which is a function of the gas pedal, is the same.

P.S. You can also supply turnAcceleration to smooth turning. This is just a simple example.

\$\endgroup\$
  • \$\begingroup\$ Thanks! A few things though: turn = 0 should not be set in Update() Also, this is not Ackermann steering. This will turn the vehicle in place without gas. And the turning radius is too wide. \$\endgroup\$ – Simian Apr 27 '17 at 6:29
  • \$\begingroup\$ I wrote this code from scratch in 5 minutes to help you, so it works exactly the way it is intended to work. Nothing stops you from modifying that turning radius, provided you grok the code. Given the principles of Ackermann steering, I have to say: Your code is also not Ackermann! So I'm simply giving you something that works and that you can adapt or mix in with your own code. \$\endgroup\$ – Engineer Apr 27 '17 at 7:55
  • \$\begingroup\$ I see. turn = 0 should not be set to 0 in update though, otherwise this doesn't work. For tighter turning, turn can be incremented with a greater value. The other modification I made is to base turn on the current speed, to prevent from turning in place. e.g. turn += Input.GetKey (KeyCode.A) ? (int) (-5.0f * speed) : 0; \$\endgroup\$ – Simian Apr 27 '17 at 8:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.