Rotational Velocity, Quaternions, Vector3 & Transfrom.rotation - Help
Hi,
I'm trying to better my understanding of programming physics so I actually understand what Rigidbody is doing which is why I'm not using Rigidbody.
I'm moving the player based on force and velocity and I'm trying to do the same for rotation.
I'm calculating the angular velocity but am having trouble passing that into the transform. This comes down to my understanding of it. I know I'm trying to pass in a vector3 to a Quaternion which is like a no no but I can't find anything to work which makes me think I'm going about it all wrong.
private Vector3 deltaYaw;
private Vector3 deltaPitch;
private Vector3 deltaRoll;
private Vector3 rotationVelocity;
private Vector3 rotationLast;
private Vector3 rotationDelta;
rotationVelocity = transform.rotation.eulerAngles - rotationLast / Time.deltaTime;
deltaYaw = transform.rotation.eulerAngles * (yawOutput * Time.deltaTime / mass);
deltaPitch = transform.rotation.eulerAngles * (pitchOutput * Time.deltaTime / mass);
deltaRoll = transform.rotation.eulerAngles * (rollOutput * Time.deltaTime / mass);
rotationVelocity += deltaYaw += deltaPitch += deltaRoll;
rotationDelta = rotationVelocity * Time.deltaTime;
transform.rotation += rotationDelta;
rotationLast = transform.rotation.eulerAngles;
transform.rotation += rotationDelta I know is never going to work but after trying many things I've left it here as that is in movement speak is what I'm trying to achieve if that makes sense.
If any one has any help or suggestions I will be very grateful. Thanks in advance.
Not sure what's going on with this particular code (you claim it has many problems?) But my general vector/angle notes are at http://www.taxesforcatses.com/vectorW/TOC.html
Thanks for the reply and the link @owen-reynolds. I will check that out.
Really the only think wrong with that code is it doesn't work. That formula (the way it's been coded at least) works for position but not for rotation.
Answer by Bunny83 · Nov 28, 2016 at 02:37 AM
Pretty much most of your calculation doesn't make much sense. Your deltaYas, deltaPitch and deltaRoll vectors is every time the same vector, just with a different length.
Why do you use "+=" three times?
rotationVelocity += deltaYaw += deltaPitch += deltaRoll;
Do you know what the operator does? You basically did this
deltaPitch = deltaPitch + deltaRoll;
deltaYaw = deltaYaw + deltaPitch;
rotationVelocity = rotationVelocity + deltaYaw;
It will place the correct value in "rotationVelocity" but all other variables are messed up as they contain the partial sum of others. You want to do this:
rotationVelocity += deltaYaw + deltaPitch + deltaRoll;
However i'm not sure what's the actual point of this. Do you want a constant acceleration? Torques are actually added just like forces, you simply add the vectors together. However from your variables it's not clear what should be what.
Just to summarize how rigidbody physics work. A rigidbody has exactly 4 state variables:
position
rotation
linear velocity
angular velocity
When using gameobjects position and rotation are already covered by the Transform component so you only have to deal with the two velocities:
Vector3 velocity;
Vector3 angularVelocity;
void Update()
{
transform.position += velocity * Time.deltaTime;
transform.rotation = Quaternion.AngleAxis(angularVelocity.magnitude*Time.deltaTime, angularVelocity) * transform.rotation;
}
That's how the current velocity and angularVelocity are applied to the object.
As i said earlier the changing of the velocity / angularVelocity based on a given acceleration is just simple addition:
void AddLinearAcceleration(Vector3 aLinearAcceleration)
{
velocity += aLinearAcceleration * Time.deltaTime;
}
void AddAngularAcceleration(Vector3 aAngularAcceleration)
{
angularVelocity += aAngularAcceleration * Time.deltaTime;
}
To convert a linear force into a linear acceleration you simply divide by the mass of the object. Converting a Torque into an angularAcceleration is much more complicated as you have to consider the objects inertiaTensor and it's rotation relative to the rigidbody. If you want to know how to apply an inertiaTensor, have a look at my answer over here.
Btw: What was your reason again why you don't want to use a Rigidbody? Because when you need other things like AddForceAtPoint or collisions things get really nasty.
@Bunny83 I have a question/comment about a line of code I read above.
transform.rotation = Quaternion.AngleAxis(angularVelocity, angularVelocity.magnitude*Time.deltaTime) * transform.rotation;
This line would surely error as AngleAxis takes two arguments, a Float first and then a Vector3 second, what you have is a Vector3 first and then a Float second.
transform.rotation = Quaternion.AngleAxis(angularVelocity.magnitude*Time.deltaTime, angularVelocity) * transform.rotation;
Could you simply switch the two arguments around such as above or would this not work either?
Yes, my bad ^^ I always get the order work. I write most answers from scratch directly in UA. The angular velocity is simply defined by a rotation around a given axis. So the vector defines the axis direction and the length of that vector specifies the amount of rotation.
I'll edit my answer and swap the arguments.
@Bunny83 thanks for the response. $$anonymous$$e and @DannyWilliams have been working on the rotation all day and still having trouble.
This is what we are trying but its not working at all. Is this what you meant?
angularVelocity = transform.rotation.eulerAngles - rotationLast / Time.deltaTime;
rotationLast = transform.rotation.eulerAngles;
// Calculates the force in the form of Vector3 using the formula
// F = m*a = m*dv/dt therefore dv = F*dt/m
deltaYaw = transform.rotation.eulerAngles * (yawOutput * Time.deltaTime / mass);
delta$$anonymous$$ch = transform.rotation.eulerAngles * (pitchOutput * Time.deltaTime / mass);
deltaRoll = transform.rotation.eulerAngles * (rollOutput * Time.deltaTime / mass);
// Takes the forces from the last forumla and adds it to the velocity.
angularVelocity += deltaYaw + delta$$anonymous$$ch + deltaRoll * Time.deltaTime;
transform.rotation = Quaternion.AngleAxis(angularVelocity.magnitude*Time.deltaTime, angularVelocity) * transform.rotation;
No, ^^ get rid of that deltaYaw, delta$$anonymous$$ch and deltaRoll nonsense. Those calculations make no sense whatsoever. I said that already in my very first sentence of my answer. Also the angularVelocity is nothing you should derive from the last and current rotation but keep it as state variable. I listed the 4 states that a rigidbody needs in my answer.
If you want to add a rotational acceleration on each local axis you would simply do:
angularVelocity += transform.up * yawOutput * Time.deltaTime;
angularVelocity += transform.right * pitchOutput * Time.deltaTime;
angularVelocity += transform.forward * rollOutput * Time.deltaTime;
given that yawOutput, pitchOutput and rollOutput should represent your angular acceleration. As i also said already you usually have to use an inertial tensor (which need to be initialized depending on the shape of your object) in order to have the correct "rotational resistance". A long thin object rotates easier around it's long axis than around one of the shorter due to mass distribution. So just dividing by "mass" would only work for completely round / equally distributed mass objects.
The inertia tensor already takes the mass into account. (Or at least you have to take it into account when creating it).
I ask again, why do you actually want to do everything manually? Those are only the easy parts of a physics engine.
Your answer
Follow this Question
Related Questions
Rotating 3d person character 0 Answers
Look Rotation Viewing Vector is Zero 0 Answers
Maintaining look at target between two cameras 1 Answer
Moving a rotating gameObject along its current angle using mouse (Unity2D) 0 Answers
Raycast under crosshair 0 Answers