# How would you go on about making a Physics based Steering Wheel?

By physics based i mean that the steering wheel is a rigidbody attached by a rotational hinge. This is because its for a VR game. Im trying to make a steering wheel that is able to turn more than 180 degrees because all solutions ive found just allowed me to move the wheel about 180 degrees before it breaks.

Sounds like theyâ€™re using .eulerAngles.

Donâ€™t use .eulerAngles.

Track your own notion of how much the steering is rotated and then drive the rotation explicitly according to whatever ratio you want the steering wheel to drive the wheel angle.

All about Euler angles and rotations, by StarManta:

https://starmanta.gitbooks.io/unitytipsredux/content/second-question.html

1 Like

What would be the best way to notion my own steering wheel value?
The way i tried it is by subtracting the x rotation by an older frames x rotation and then constantly adding the frameâ€™s result to a variable. I feel like this â€śshouldâ€ť work but i think by the way quaternions are set up it doesnt.

Attached is a simple â€śdial with your fingerâ€ť demo.

Around about line 56 is where it rotates the transform by angleDelta.

Modify the above to keep your own float steer angle and update it by angleDelta.

``````private float mySteerDirection;
``````

like so:

``````mySteerDirection += angleDelta;
``````

and use mySteerDirection however you want to turn your wheel collider or your hinge, probably by scaling it way down, perhaps dividing it by 10 or something.

i cant express how thankfull i am for this help, but what i was needing help with is getting the rotational value in sort of a specific way, since the rotation itself is already gonna be handeled by the rigidbody and the players hand i only need the rotation in such way where when i for example turn the wheel 360 degrees to the right it would return 360 and if i spin it once more to the right its gonna return 720, third one would be 1080 and it would just keep going like that. when you would start turning left again and lets say you do a whole 360 degree turn, the value would now reverse and go back to 720. i hope that makes sense and i apologize for not explaining correctly.

Iâ€™m sorry, the assertion I made above was incorrect. The number does not fully accumulate.

See several posts below (presently Post #16) for a true RevolutionCounter script. Nothing else in this post is guaranteed.

DISREGARD THE BELOW!!

I fixed it so that it accumulates forever as you turn the dial. Here it is in action.

Use the above package I posted, but replace the script with this:

(changes have been flagged with `// related to degree accumulation`)

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

// by @kurtdekker
// simple example of rotating something like a dial on a safe
//
// EDIT: this has been tweaked to sum and report total degrees turned.
//

public class RotateZViaDrag : MonoBehaviour
{
public bool RotateAroundAxis;

Vector3 lastPosition;

// related to degree accumulation
private float mySteerDirection;
public UnityEngine.UI.Text DegreeOutput;

void OnMouseDown()
{
lastPosition = Input.mousePosition;
}

void PerformLinearRotation()
{
Vector3 currPosition = Input.mousePosition;

Vector3 difference = currPosition - lastPosition;

lastPosition = currPosition;

// now choose what axis to care about... this adds X and Y
float change = difference.x + difference.y;

// and it rotates it around the Z (forward)
transform.Rotate(new Vector3(0, 0, change));
}

void PerformCircularRotation()
{
// where is our center on screen?
Vector3 center = Camera.main.WorldToScreenPoint(transform.position);

// angle to previous finger
float anglePrevious = Mathf.Atan2(center.x - lastPosition.x, lastPosition.y - center.y);

// related to degree accumulation
Vector2 arm1 = new Vector2(center.x - lastPosition.x, lastPosition.y - center.y);

Vector3 currPosition = Input.mousePosition;

// angle in radians to current finger
float angleNow = Mathf.Atan2(center.x - currPosition.x, currPosition.y - center.y);

// related to degree accumulation
Vector2 arm2 = new Vector2(center.x - currPosition.x, currPosition.y - center.y);

lastPosition = currPosition;

// how different are those angles?
float angleDelta = angleNow - anglePrevious;

// scale up to degrees (everything above is in radians!)
angleDelta *= Mathf.Rad2Deg;

// related to degree accumulation
// compare the arms and accumulate distance
float steerDelta = Mathf.Asin( Vector3.Cross( arm1.normalized, arm2.normalized).z) * Mathf.Rad2Deg;
mySteerDirection += steerDelta;
Debug.Log( ((int)mySteerDirection).ToString());
if (DegreeOutput) DegreeOutput.text = ((int)mySteerDirection).ToString();

// rotate by that much
transform.Rotate(new Vector3(0, 0, angleDelta));
}

void OnMouseDrag()
{
if (RotateAroundAxis)
{
PerformCircularRotation();
}
else
{
PerformLinearRotation();
}
}
}
``````

Where the mouse input happens (the position and previous position that feed into `arm1` and `arm2` vectors) can be replaced with just any arbitrary Transform parented below your steering wheel.

NOTE: this works as rotations around the Z+ axis.

Thank you so much! The accumulation is exactly what i needed, but how would i convert this to 3D? My steering wheel does not use player inputs like the mouse since its a vr game. it uses hands that will rotate the wheel. So the whole Rotating part i already got settled. I only need this accumilation mechanism that tracks how much the wheel rotated and if possible would this also work for the X Axis?

See several posts below (presently Post #16) for a true RevolutionCounter script. Nothing else in this post is guaranteed.

I think my original statement might have been a bit strong.

Nothing about the computation on line 70 is tied to any axis.

It does however presume that the axis of the wheel is not changing over its course. That would introduce error.

The dependence on +Z axis is simply from the creation of arm1 and arm2, which are x/y Vector2s.

I suspect it would work fine in another orientation as long as you were consistently tracking a rotating part of the wheel.

what about the script should i exactly be changing to make it work with my case? For reference my wheel is a child of a pirate ship model. it has a hingejoint component to attach it to the ship and a rigidbody. I want to know what I can change, remove, not remove, etc

See several posts below (presently Post #16) for a true RevolutionCounter script. Nothing else in this post is guaranteed.

Instead of computing arm1 / arm2 the way I did above, compute it as the Vector difference between the center (hub) and a single fixed point on the wheel. Doesnâ€™t matter where the point is, it just canâ€™t be at the center.

The code above will observe that pointâ€™s rotation in the same way that it observes the mouse motion above.

Could you please give me an example?

See several posts below (presently Post #16) for a true RevolutionCounter script. Nothing else in this post is guaranteed.

Iâ€™ve told you everything. Get the vector from the hub of your wheel and a point on the wheel (this frame and last) and feed that into the computations at line 70 above. Thatâ€™s it, honest.

Thank you very much for the help I appreciate it. Iâ€™ll give it a try

See several posts below (presently Post #16) for a true RevolutionCounter script. Nothing else in this post is guaranteed.

I tried to replicate this based on what I told you above and there is still one assumption of +Z in line 70: the use of the .z component of the computed cross product.

Iâ€™m sorry but I donâ€™t have time to dig further into it right now. I suggest perhaps using the Transform of your actual steering wheel to compute the inverse position of an observed point so that once it feeds into the arm1 / arm2 calculation, it is normalized to the global +Z axis.

No problem man. Thank you for the help.

Heh, youâ€™re very welcomeâ€¦ I think I was getting tangled up in my â€śRotate Zâ€ť demo code.

It was bugging me so much I pushed into it and solved it.

This is WAY simplified: just place this script on a Transform anywhere in any orientation.

It will read out the accumulated degrees rotated around the Transformâ€™s local +Z

https://gist.github.com/kurtdekker/ad051f56462f72a7e184269d9bece32f

You just get a reference to this script and read it out of the `TotalDegrees` field.