Changing a Rigidbody's Rotation Midflight

If I have a rigidbody traveling along at a given speed and I want to change its rotation and have it continue along but now vectored by it’s new rotation, how do I do that?

I’ve tried just changing the rotation of the rigidbody, but that appears to change the orientation of the associated mesh while retaining the original velocity vector.

RaceCraft has a similar issue. I’ve learned to control around it, but I’m not sure that players would be too thrilled by it taking so long to change directions.

There are two ways about it.

  1. Actually directly modifying rigidbody.velocity whenever you rotate the craft

Whenever you apply a rotation. Do
Quaternion.Euler (x, y, z)
multiply that by the current velocity and set the rotated vector to be the new velocity.

  1. Making a flight model where a lot of drag is applied each frame. But you also have a lot of forward force, thus the velocity very quickly approaches the forward direction. This is more physically correct and works really well if you apply the drag force only sideways.

the vehicles example project has a couple of vehicle scripts that use the second technique. www.otee.dk/examples/VehiclesExample.zip

Thanks, Joe.

Any chance you could translate your pseudocode in example 1 into Unity Javascript? I’m still trying to get the hang of programming Quaternions directly.

not sure if this is what you’re going for, marty but see my second post in this thread:

http://forum.unity3d.com/viewtopic.php?t=4768&start=0

there’s a web player there too. so you can see how it’s supposed to act.

Thanks, Pete.

This might help.

My head hurts right now though. :wink:

well don’t try to understand Quaternions. just know they work! here, i’ll try to explain what the script does.

var speed = 30.0;
var smooth = 2.0;
var maxSteeringAngle = 90.0;

private var moveDirection = Vector3.zero;
private var currentRotation : Quaternion;
private var targetRotation : Quaternion;

function Update()
{
//we want this in update so it adjusts rotation every frame.

// we need to establish our rotation so it doesn't keep going back to the original or 0,0,0

   currentRotation = transform.rotation;

// now we're going to read the horizontal input and apply it to the Y axis. since Y is vertical it rotates left and right. max steering angle is adjustable in the inspector and helps with control. you can also set a target for X and Z to do pitch and yaw but i didn't do that here.

   targetRotation = Quaternion.Euler(0,  Input.GetAxis("Horizontal") * maxSteeringAngle, 0);

//now we want to set our angles up to be used in the slerp below. since i'm only dealing with Y, i did it this way. iirc i had a prob with just currentRotation.eulerAngles += targetRotation.eulerAngles; which is why i have .y don't really remember

   currentRotation.eulerAngles.y += targetRotation.eulerAngles.y;

//now we're going to slerp our transform between what it is now and what we just set currentRotation to. smooth is adjustable in the inspector and just helps um smooth the slerp.

   transform.rotation = Quaternion.Slerp(transform.rotation, currentRotation, Time.deltaTime * smooth);
}

function FixedUpdate()
{
// this just handles applying force to the Z based on  the vertical input. we want to apply it in fixed update so it's not framerate dependent. speed is adjustable in the inspector.

   moveDirection = new Vector3(0, 0, Input.GetAxis("Vertical"));
   moveDirection = transform.TransformDirection(moveDirection);
   rigidbody.AddForce(moveDirection * speed);
}

function Start(){
//we don't want the physics engine spinning us
   if(rigidbody){
      rigidbody.freezeRotation = true;
   }
}

eh! probably gave you a bigger headache! :slight_smile:

Thanks, Pete.

I actually got my thing to work with some math Joe was kind enough to share off-forum.

Nonetheless, your code looks sweet and way too well-written to not be useful.

Could you maybe post a stripped down sample project demonstrating it in action?

TIA!

http://www.oculardgi.com/steeringExample.zip

this one’s a project. the object will drift - it’s not a hard turn. mess around with speed, drag and steering angle on the capsule.

Maybe you could post what you ended up with marty. might be useful to others.

Actually, the math that Joe helped me with wouldn’t work exactly in my application since I need to rotate the RB’s velocity vector based on RayCast hit data that isn’t always Y-up.

But his math/assistance was pretty inspiring nonetheless and got me to thinking differently about my approach.

Eventually, I ended up letting the RB do what it wants (so my physics don’t end up looking odd) and just rotated the associated mesh to conform to the RB.

I built this in my last game…

modifying velocity gave weird results as Unity says (unphysical results)–and my object wasn’t powered so adding force didn’t “feel” right.

I did this in fixed update…

 //remove speed
    rigidbody.AddRelativeForce (0,0,-forcebalance);
    
    
    //turn the craft
  	transform.Rotate(Vector3.up, steer);

    
    //add speed back
    rigidbody.AddRelativeForce (0,0,forcebalance);

The idea is, remove all the speed, turn, add the same amount back in the new direction, per frame.

Force worked better than velocity for whatever reason. The tricky part is balancing the force so it takes into account the velocity and mass of the object.

Can’t you use ForceMode.Acceleration?

http://unity3d.com/Documentation/ScriptReference/ForceMode.html

Psh. That sounds too easy. :wink:

Actually, there was still a -fudge- coefficient that I never figured out why it was there, even after digging back into my physics knowledge…
But, it works…

The trick was making sure it never applied more negative force than would completely stop the craft, so it had to scale with velocity.

It looks like a total hack, but it drives like a dream.

Look at car games on consoles, that sure as hell isn’t realistic car physics.
Games physics is fudged physics. How many of you guys can move while jumping? If it feels good it’s right.