I've been trying to get the vector that represents the local rigid body's true forward pointing (z axis, or blue colored) vector. I've been using Debug.DrawLine(...)
to try and find out which position vector to use.
Debug.DrawLine(_rb.position, new Vector3(_rb.position.x, _rb.position.y, _rb.position.z + 10), Color.red, .01f, true);
Debug.DrawLine(_tf.position, new Vector3(_tf.position.x, _tf.position.y, _tf.position.z + 10), Color.green, .01f, true);
Debug.DrawLine(transform.forward, new Vector3(transform.forward.x, transform.forward.y, transform.forward.z + 10), Color.blue, .01f, true);
Debug.DrawLine(transform.forward, new Vector3(transform.forward.x, transform.forward.y, transform.forward.z + 10), Color.yellow, .01f, true);
rb.position
and tf.position
appear to be equivalent, while transform.forward
and Vector3.forward
are equivalent but are in the world's (x,y,z)
0 position. All four have the same orientation when I change the orientation of the Rigidbody
via it's angular velocity property.
Why do you need the local z axis orientation?
I'm implementing a Vehicle in unity without using Wheel Colliers because they don't have the level of control that I want, and their physics are extremely wonky. Being able to obtain a vector representing the z axis orientation makes it very easy to turn the car, since I only have to modify the Rigidbody.angularVelocity
function to get it to turn.
Code for reference
For reference, my driving controller code consists of three steps within the FixedUpdate()
method.
First is the simple Turning algorithm, which creates a triangle relationship with the front and back wheel of the car and the requested steering angle and then factors this relationship into a rate of change of angular velocity:
if (Input.GetButton("Right")) {
_steerAngle = 45;
var l = Mathf.Abs(Vector2.Distance(new Vector2(BL.position.x, BL.position.z), new Vector2(FL.position.x, FL.position.z)));
turningCircleRadius = l / Mathf.Sin(_steerAngle);
_rb.angularVelocity = new Vector3(_rb.angularVelocity.x, new Vector2(_rb.velocity.x, _rb.velocity.z).magnitude / _turningCircleRadius, _rb.angularVelocity.z);
} else if (Input.GetButton("Left")) {
steerAngle = -45;
var l = Mathf.Abs(Vector2.Distance(new Vector2(BR.position.x, BR.position.z), new Vector2(FR.position.x, FR.position.z)));
_turningCircleRadius = l / Mathf.Sin(_steerAngle);
_rb.angularVelocity = new Vector3(_rb.angularVelocity.x, new Vector2(_rb.velocity.x, _rb.velocity.z).magnitude / _turningCircleRadius, _rb.angularVelocity.z);
} else {
_steerAngle = 0;
_rb.angularVelocity = new Vector3(0, 0, 0);
_turningCircleRadius = 1 / 0f;
}
Then the force exerted by the engine is calculated and then converted into change in velocity:
var latSpeed = new Vector2(_rb.velocity.x, _rb.velocity.z).magnitude;
if (Input.GetButton("Accelerate")) {
var force = _rb.mass * 10;
latSpeed += force / _rb.mass * Time.fixedDeltaTime;
} else if (Input.GetButton("Brake")) {
var force = -1 * 1000 * _rb.mass;
latSpeed += force / _rb.mass * Time.fixedDeltaTime;
if(latSpeed <= 0) latSpeed = 0;
}
Finally, the velocity is modified:
_rb.velocity = new Vector3(transform.forward.x * latSpeed, _rb.velocity.y, transform.forward.z * latSpeed);
As you can see this driving algorithm would work fine on a completely flat surface, but would start to have wonky interactions with hills if the vehicle's pitch were to change.