- Home /
Turning a rigidbody that's in motion
I am creating a script to handle the movement of my "player" which happens to be a skateboard that has a rigidbody with a box collider attached to it. To move it forwards and backwards I add a relative force to the rigidbody. However I'm having trouble with getting the object to turn correctly. I have gotten it to turn by adding a torque but the results were not what I am looking for. I want to be able to turn the board while its "coasting" along. What I mean by "coasting" is that no new force can act on the object. I know I may have to keep adding some small amount of force after the rotation, however what I want to simulate is the rider has stopped pushing and now has both feet on the board and is turning. Eventually coming to a stop depending on how much force was added to the board.
For the turning aspect I've thought about using Vector3.forward as the movement vector that will face the direction where the board is currently heading and then have another vector offset a certain degree from Vector3.forward. This turn Direction vector will be where the board needs to rotate to. Then get the cross product of these two vectors and rotate about that vectors axis by said degrees. I would like to vary the amount of turn depending on player input.GetAxis("Horizontal"), negative would be a left turn, positive a right turn.
However I cannot seem to figure out how to generate the turn direction vector that is a specific degree away (depending on the player) from the movement vector. Im also not sure how to handle the actual rotation as well. I am assuming using Quaternion. Here is a picture of what I am thinking
Here's the little bit of working code I have.
void Update ()
{
turnAmount = Input.GetAxis("Horizontal");
thrustAmount = Input.GetAxis("Vertical") * 10;
moveDirection = Vector3.forward;
}
void FixedUpdate()
{
if((rigidbody.velocity.magnitude <= maxSpeed) && (!turning))
{
rigidbody.AddRelativeForce(moveDirection * thrustAmount);
}
}
Any help would be much appreciated.
Answer by robertbu · Mar 20, 2014 at 03:10 AM
Try something like this:
if (turning) {
Quaternion q = AngleAxis(turnAnglePerFixedUpdate, transform.up) * transform.rotation;
rigidbody.moveRotation(q);
float mag = rigidbody.velocity.magnitude;
rigidbody.velocity = transform.forward * mag * dampingFactor;
}
This is untested, but I've played with similar things, and they worked well. My main concern is how this code will interact with any angular velocity of the board. Set 'dampingFactor' to some value slightly under 1.0 like 0.995 to start. 'turnAnglePerFixedUpdate' is how much you want to turn each fixed update call. You can adjust it for faster or slower turns.
Thanks for the quick response! I'll test this later today and let you know how it works. Just so I can make sure I understand the logic of your code. What it does is first it calculates how much rotation is needed to be done from the objects current rotation then rotates the object. Then changes the velocity to account for slowing down. This code seems much easier than what I was originally thinking would have to be done.
In addition to the actions you list, line 5 also changes the velocity vector so that the direction of travel is on the new forward of the board.
Just tested it and it seems to work wonderfully on flat surfaces with no dampingFactor. However if I approach a ramp at a certain velocity and try and turn I slow down extremely fast and cannot complete the turn. I'm not sure if this is because of the script or something else like friction. Other than that its great though.
Your slowdown is likely due to other factors. This code will always slow down at a fixed rate from any specified initial velocity. Look to friction and even gravity.
Alright I will look into the other factors. Thanks so much for your help I really appreciate it!
@Dnileok Could you please post the resulting movement code, that you have used for your model? I've stuck here like couple days, can't find the way out :( I would really appreciate that!