- Home /

# Snap a direction vector

I have a vector3 direction (target.position - transform.position) which I'd like to snap along the y-axis to 8 directions so that it can be any direction x and z, but be snapped to the nearest 45 degrees on the y.

I've tried many different things like converting the vector to a quaternion, then to a euler, and trying to snap those values and putting them back into a vector but getting half working results. Trying to snap the quaternion itself instead of converting it to euler angles, but getting strange results that snap correctly at certain angles and completely go off in a different direction on other angles.

I'm pretty bad at math so I'd like to at least know the correct way to do this, and if you're feeling generous, some pseudocode as well.

Here are the few things I've tried

Find the angle between the direction and down vector (0,-1,0)

Check if that angle is closer to 0 or 45 (angle % 45 == closer to 0 or 45) (this works correctly so far using two if statements)

Attempt to rotate the Vector3. "snappedDirection = Quaternion.AngleAxis(angle % 45, Vector3.up) * originalDirection;"

Attempt being the keyword here. This only half works, and I could probably get it working if I had some help understanding the correct way to use Quaternions to rotate vectors.

Convert direction to Quaternion using LookRotation, then convert to Euler.

Snap those Euler angles using same method.

Convert back to to Quaternion, then multiply by Vector3 axis used during LookRotation (up vector) This one works on one side, but not the other, and probably won't ever work the way I'm doing it since I lose data when compressing the Quaternion into a Euler or something like that.

I've been stuck on this for over two days and am in a rut, getting frustrated here. Any help at all would be greatly appreciated, thanks!

Edit: Here is code of the first attempt I described above. It doesn't work properly but should show what I'm trying to achieve.

```
float num = Vector3.Angle(oDirection, Vector3.up);
float snapAngle = 360 / angles;
if (num % snapAngle > 0 && num % snapAngle < snapAngle / 2)
{
newDirection = Quaternion.AngleAxis(num % snapAngle, Vector3.up) * oDirection;
}
else if (num % snapAngle < snapAngle && num % snapAngle > snapAngle / 2)
{
newDirection = Quaternion.AngleAxis(snapAngle - (num % snapAngle), Vector3.up) * oDirection;
}
```

Basically I have an "explosion" that sends force, but I want to limit that force vertically so that the objects would only receive force at an angle of 0/45/90/.../315 degrees. However the objects should still be pushed sideways at any angle. Please refer to my crude drawings.

**Answer** by robertbu
·
Jul 15, 2013 at 01:29 AM

Here is a SnapTo() methods that snaps the vector to the specified angle. It works by generating the cross product between the direction and Vector3.up to create an axis for rotation. Then it does an AngleAxis rotation to snap the vector to the angle.

```
Vector3 SnapTo(Vector3 v3, float snapAngle) {
float angle = Vector3.Angle (v3, Vector3.up);
if (angle < snapAngle / 2.0f) // Cannot do cross product
return Vector3.up * v3.magnitude; // with angles 0 & 180
if (angle > 180.0f - snapAngle / 2.0f)
return Vector3.down * v3.magnitude;
float t = Mathf.Round(angle / snapAngle);
float deltaAngle = (t * snapAngle) - angle;
Vector3 axis = Vector3.Cross(Vector3.up, v3);
Quaternion q = Quaternion.AngleAxis (deltaAngle, axis);
return q * v3;
}
```

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.