- Home /

# Rotate an object until its x axis lies in a plane perpendicular to a given vector...

I want a spaces$$anonymous$$p to rotate on its forward axis until its right axis is (relatively) perpendicular to a surface normal. I don't, however, want to force the spaces$$anonymous$$p's up axis to align specifically with the surface normal - e.g. I want the spaces$$anonymous$$p's up axis to be unrestricted so that it can look up and down to any desired degree. T$$anonymous$$s amounts to keeping the spaces$$anonymous$$p's right axis wit$$anonymous$$n a plane perpendicular to the surface normal.

I have a script that accomplishes t$$anonymous$$s behavior by performing a test rotation on a c$$anonymous$$ld empty, checking the before and after dot product of the empty's right vector to see if the test rotation moves the dot product closer to zero, and rotating the s$$anonymous$$p's forward axis in the appropriate direction. T$$anonymous$$s, however, strikes me as quite messy - I keep wondering if there's a simpler way that dispenses with the additional game object and test rotations. Mathematically, I know that I just need to find the projection of the s$$anonymous$$p's right axis on a plane through the s$$anonymous$$p parallel to the surface and rotate the right axis towards that projection, but I'm not sure of how to do t$$anonymous$$s in Unity.

**Answer** by Bunny83
·
Oct 11, 2016 at 01:21 AM

Well, first to answer your first question on how to project the object's local-x-axis onto the ground place defined by a ground normal. Unity now has the method Vector3.ProjectOnPlane w$$anonymous$$ch should do exactly what you asked for. It simply does t$$anonymous$$s:

```
public static Vector3 ProjectOnPlane(Vector3 vector, Vector3 planeNormal)
{
return vector - Vector3.Project(vector, planeNormal);
}
```

So it actually projects your vector onto the normal and then simply subtracts that part from the original vector w$$anonymous$$ch will project it onto the place defined by the normal vector.

"Vector3 Project" on the other hand simply does t$$anonymous$$s:

```
public static Vector3 Project(Vector3 vector, Vector3 onNormal)
{
float num = Vector3.Dot(onNormal, onNormal);
if (num < Mathf.Epsilon)
{
return Vector3.zero;
}
return onNormal * Vector3.Dot(vector, onNormal) / num;
}
```

Since the normal vector is involved two times as a factor we don't have to normalize the normal vector but can simply divide by the square magnitude (num).

Finally another way is to simply use the Cross product between your normal vector and your forward vector. T$$anonymous$$s gives you the "right" vector that you're after as well. Unity uses a left-handed-system so the left-hand-rule applies:

```
Vector3 right = Vector3.Cross(normal, transform.forward).normalized;
```

Of course when you pull up over 90° right will flip to the other side as you officially are now upside down.

To get the relative rotation you might use Quaternion.FromToRotation. However i guess you want to apply a torque instead of rotating it manually, right?. So all you have to determine is:

how far you have to rotate (the remaining angle) so you can adjust the rotation speed

W$$anonymous$$ch direction you have to rotate.

To get the remaining angle you can simply use Vector3.Angle with your object's right vector and the calculated target right vector.

To determine the direction you have to rotate, simply use the Dot product between the surface normal and your right vector. If the result is positive you have to rotate clockwise (as seen from be$$anonymous$$nd looking along forward) and if it's negative you have to rotate counter-clockwise.

Note: you might disable the alignment if you almost go straight up or down (+-70°) to avoid constant realignment by 180° each time you cross the zenith.

### Your answer

### Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

### Follow this Question

### Related Questions

Rotate one vector towards another but keeping it on the same plane 1 Answer

Sorting an array of vectors in javascript 1 Answer

Vector math problem 2 Answers

Drag/Move an object perpendicular to starting point 1 Answer

Time Freezer 1 Answer