How can I rotate a steering wheel to its original rotation in Unity3D?

2.2k views Asked by At

I have been searching for an answer for hours, and I cant find the solution. I have a script that rotates a steering wheel when the car is turning. It has maximum rotation of 120 and a minimum rotation of -120. I have been trying to rotate with RotateTowards and other Quaternion methods but I can't figure them out. How can I make it when the turning angle is not zero and turning keys (a and d) are not pressed, it goes to its original rotation of 0, 0, 0, at a certain speed?

Here's my script for the steering wheel:

    if (horizontalInput > 0)
    {
        wheel.transform.Rotate(Vector3.forward*Time.deltaTime*wheelspeed);
        rotations -= wheelspeed;
    }
    else if (horizontalInput < 0)
    {
        wheel.transform.Rotate(-Vector3.forward * Time.deltaTime * wheelspeed);
        rotations += wheelspeed;

    }

And here is my (very bad) script for the minimum and maximum rotation of the steering wheel:

    angle += Input.GetAxis("Horizontal") * Time.deltaTime*10;
    angle = Mathf.Clamp(-120, angle, 120);
    wheel.transform.localRotation = Quaternion.AngleAxis(angle, Vector3.forward);
    
   
    angle += Input.GetAxis("Horizontal") * Time.deltaTime * 400;
    angle = Mathf.Clamp(120, 0, angle);
    wheel.transform.localRotation = Quaternion.AngleAxis(angle, Vector3.forward);
2

There are 2 answers

4
gbe On BEST ANSWER

You should do something like this for the steering wheel script:

float rotateBack = 0f;
float angle = 0f;

void Update(){
 angle += Input.GetAxis(“Horizontal”) * Time.deltaTime * 10;
 angle = Mathf.Clamp(angle, -120, 120);
 if (Input.GetAxis(“Horizontal”) == 0 && angle != 0f){
  angle += rotateBack * Time.deltaTime;
  if (angle > 0){
   rotateBack = -10f;
  }
  else{
   rotateBack = 10f;
  }
 }
 transform.rotation = Quaternion.Euler(0f, 0f, angle);
}

What this does is setting a variable of angle to the input times a value to increase turning speed. Then it clamps if so it doesn’t go over 120, or under -120. Then, if there is no input and the angle isn’t zero: it will change the variable by how much to rotate back. The rotate back variable is set to either positive or negative based on which direction the steering wheel needs to be turned. The only problem with this script that I could see is the angle not being exactly 0, continuing the if statement. If this error affects your game, use the Mathf.Round(); function. (If there are any errors, comment on this post.)

0
Ruzihm On

I would do what @ken is doing, but refactor the speed factors and other constants into fields so they are more easily changed and also use Mathf.MoveTowardsAngle to move the angle back to its neutral position.

[SerializeField] float rotateBackSpeed = 3f; // degrees per second
[SerializeField] float rotateSpeed = 10f;    // degrees per second
[SerializeField] float angle = 0f;           // degrees
[SerializeField] float minAngle = -120f;     // degrees
[SerializeField] float maxAngle = 120f;      // degrees
[SerializeField] float neutralAngle = 0f;    // degrees

void Update()
{
    angle = Mathf.Clamp(angle + Input.GetAxis(“Horizontal”) * rotateSpeed 
            * Time.deltaTime, minAngle, maxAngle);

    if (Mathf.Approximately(0f, Input.GetAxis(“Horizontal”))) 
    {
        angle = Mathf.MoveTowardsAngle(angle, neutralAngle, 
                rotateBackSpeed * Time.deltaTime);
    }

    transform.eulerAngles = angle * Vector3.forward;
}