using lerp and up vector to self right a submarine

Hi, Just starting unity and I'm liking it.

I am trying to make a submarine game. I have a rigidbody with no gravity for the sub that I am AddingForceAtPosition at the propeller points to control. This is working great.

My problem is, I would like the submarine to self-right. In other words, when left on its own, I would like its up vector to slowly return to the world's up vector. I am trying to use the following line of code in the sub's Update function:

rigidbody.transform.up = Vector3.Lerp(rigidbody.transform.up,Vector3(0,1,0), Time.deltaTime * rightendamping);

Unfortunately, this not only rightens the sub, but points it along the Z axis. I would like it to maintain its heading in the x and z plane. Any clue how I would do this?

Thanks!

-Matt

you can lock rotations since it's a rigidbody

3 Answers

3

I'd go with using quaternions for it:

var planarFwd = transform.forward;
planarFwd.y = 0;
rigidbody.rotation = Quaternion.RotateTowards(rigidbody.rotation, Quaternion.LookRotation(planarFwd), rightenddamping * Time.deltaTime);

Nah, you'll often get things in all three axes, quaternions are weird like that. I'll double check the example to make sure that everything is ok

That'd fairly odd - it works perfectly for me (using a fake submarine made of cubes at that). What kind of values are you using for the rightenddamping?

This was how I finally solved it:

var forwardxz = rigidbody.transform.forward;
forwardxz.y = 0;
rigidbody.transform.forward = Vector3.Lerp(rigidbody.transform.forward, forwardxz, rightendamping * Time.deltaTime);

Thank-you Mike for pointing me towards the forward vector rather than the up vector. Still not sure I understand Quaternions or why I should use them here. The "RotateTowards" function wasn't working for me. This did the trick though.

Added a new example, should be a little more stable than changing the forward vector (which could flip out without warning)

AFAIK, a Quaternion is just an intimidating name for a rotation. The Transform's Rotation in the Inspector is actually a Quaternion with the w-value hidden. That'd be the regular way to rotate a character(like Mike propose), opposed to your way of... redefining the whole GameObject axis? I didn't even know one could do that,heh.

The above isn't correct. The rotation as displayed in the inspector is not the x/y/z elements of the corresponding quaternion; it's the rotation in Euler-angle form. (Also, strictly speaking, 'quaternion' isn't synonymous with 'rotation'. Quaternions are obviously useful for representing and manipulating rotations, but fundamentally, the quaternions are just a number system, which is much more general.)

I thought I would add my control code in case anything else I'm doing makes a difference. Here is my sub control script so far. I haven't implemented diving propellers yet, because I hadn't been able to get the self righting, but you can get some dive by adjusting the Yoffset.

    var forceXoffset : float = 0.1;

var forceYoffset : float = 0.0; var maxThrust : float = 2.0; var rightendamping : float = 3.0;

function Update () {

var thrustdirection = rigidbody.transform.forward;

var forwardxz = transform.forward;
forwardxz.y = 0;

transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(forwardxz), rightendamping * Time.deltaTime);

if(Input.GetKey("q"))
{
    rigidbody.AddForceAtPosition(thrustdirection*maxThrust, (transform.TransformPoint(Vector3(-forceXoffset,forceYoffset,0))));
}
if(Input.GetKey("e"))
{
    rigidbody.AddForceAtPosition(thrustdirection*maxThrust, (transform.TransformPoint(Vector3(forceXoffset,forceYoffset,0))));
}

}