# Faking normal by some angle?

Hi,

I am making a 2D game in which an object deflects of the wall. I am able to get the reflection vector easily by using Vector2.Reflect method. passing the inDirection and the surface normal. The question: is it possible to fake the normal? I know normal is always perpendicular to the surface(90 Degree) But I want it to be a little less or more based on a condition(±45). The image will explain it better.

The blue line is the normal result, I want to get the one in red

There’s various ways of doing that but here’s one way that should work:

``````        // Create the normal vector of the surface (in this case just a horizontal plane facing upwards)
Vector2 normalVec = new Vector2( 0.0f , -1.0f );

// Create the incoming vector (in this case just a ray pointing straight down)
Vector2 rayVec = new Vector2( 0.0f , 1.0f );

// Create the reflection vector (in this case a ray pointing straight up)
Vector2 reflectVec = Vector2.Reflect( rayVec , normalVec );
Vector2 reflectVecWithOffset = new Vector2();

// Find the angle of the reflection vector (in radians)
float reflectAngle = Mathf.Atan2( reflectVec.y , reflectVec.x );

// Add a plus/minus 20 degree offset to that angle
reflectAngle += UnityEngine.Random.Range( -20.0f , 20.0f ) * Mathf.Deg2Rad;

// Create a new normal vector with the offset on it
reflectVecWithOffset.x = Mathf.Cos( reflectAngle );
reflectVecWithOffset.y = Mathf.Sin( reflectAngle );

// 'reflectVecWithOffset' is now your reflected vector with some offset
``````

Rotate the normal vector by X degrees before you use it in Vecto2.Reflect.

I don’t think Unity specifically has a ‘Vector2.Rotate’ method (maybe they’ve added it… but they didn’t before).

Here is my own implementation:

``````        public static Vector2 RotateBy(Vector2 v, float a, bool bUseRadians = false)
{
var ca = System.Math.Cos(a);
var sa = System.Math.Sin(a);
var rx = v.x * ca - v.y * sa;

return new Vector2((float)rx, (float)(v.x * sa + v.y * ca));
}
``````

Just stick whatever angle you want in, + or -.

1 Like

Another way which leans on Quaternion.AngleAxis to avoid doing maths :

``````Vector2 surfaceNormal;
float angleOffset;

Vector2 rotation = Quaternion.AngleAxis(angleOffset, Vector3.forward);
Vector2 rotatedNormal = rotation * surfaceNormal;
``````

I mean… it’s still doing the maths. Just different kind of maths (3d to be specific).

Yes, but I’m not doing the maths lol.

However now that I’m thinking about this more, it’s probably best to calculate the axis of rotation rather than assuming Vector3.forward, because if the reflection is inverted, the rotation axis would be inverted as well.

So then it would be more like:

``````float angleOffset;
Vector2 surfaceNormal;
Vector2 projectileVector;

Vector3 orthogonalAxis = Vector3.Cross(surfaceNormal, projectileVector);
Quaternion rotation = Quaternion.AngleAxis(angleOffset, orthogonalAxis);
Vector2 rotatedNormal = rotation * surfaceNormal;
``````

I think this approach would work for 2D or 3D. I decided to make a little test for this just to be sure this works the way i think it does:

Green = incoming vector
Blue = surface normal
Red = rotated normal
Yellow = reflection over rotated normal
Pink = axis of rotation

Test code:
Test.cs

``````using UnityEngine;

public class Test : MonoBehaviour
{
public Transform aim;
public float angleOffset = 5;

private void Update()
{
if (aim != null)
{
Ray ray = new Ray(aim.position, aim.right);
if (Physics.Raycast(ray, out RaycastHit hitInfo))
{
float lineLength = hitInfo.distance;

Vector2 surfaceNormal = hitInfo.normal;
Vector2 projectileVector = ray.direction;

Vector3 orthogonalAxis = Vector3.Cross(surfaceNormal, projectileVector);

Quaternion rotation = Quaternion.AngleAxis(angleOffset, orthogonalAxis);

Vector2 rotatedNormal = rotation * surfaceNormal;

Vector3 rotatedReflection = Vector3.Reflect(projectileVector, rotatedNormal);

Debug.DrawRay(ray.origin, projectileVector * lineLength, Color.green);      // projectile vector
Debug.DrawRay(hitInfo.point, surfaceNormal * lineLength, Color.blue);       // surface normal
Debug.DrawRay(hitInfo.point, orthogonalAxis.normalized * lineLength, Color.magenta);   // axis of rotation
Debug.DrawRay(hitInfo.point, rotatedNormal * lineLength, Color.red);        // new rotated normal
Debug.DrawRay(hitInfo.point, rotatedReflection * lineLength, Color.yellow); // new rotated normal reflection
}
}
}
}
``````