Does Vector3.Normalize() check to see if a vector is already normalized?

I tend to call Vector3.Normalize() on any direction vector after passing it to one of my functions, regardless of whether it is already normalized. (Just to be safe, and so the calling code can be flexible without having to worry about normalizing beforehand.) As I recall, though, normalizing requires the costly square root operation. I’m not sure how anyone would know, but I’d like to try asking anyway: Does the default Normalize() function check the length of a vector before proceeding, or do I need to be a little more careful about performance?

With these things, the best way to be sure is to try for yourself!

I created an already normalized vector (1,1,1) and performed 2 operations:

  • myVect.Normalize();
  • if (myVect.magnitude != 1) myVect.Normalize();

These cover your question, but I added 2 operations more:

  • vectToSet = myVect.normalized;
  • if (vectToSet.magnitude != 1) vectToSet = myVect.normalized;

vectToSet being another already normalized vector (also 1, 1, 1).

Results

+-----------------------------------+-------------------+
|             Operation             | Time (in seconds) |
+-----------------------------------+-------------------+
| No Checking:                      | 0.6968285         |
| Checking:                         | 0.2933789         |
| No Checking (Vector3.normalized): | 0.7552377         |
| Checking (Vector3.normalized):    | 0.2898996         |
+-----------------------------------+-------------------+

So, seeing the results we can say that no, it doesn’t check if it’s normalized.

The code


using UnityEngine;
using System.Collections;
public class NormalizeCheckTest : MonoBehaviour {
	// Use this for initialization
	void Start () {
		
		int iterations = 9999999;
		
		float s;
		float e;
		
		Vector3 myVect = new Vector3(1, 1, 1);
		Vector3 vectToSet = new Vector3(1, 1, 1);
		
		/////////////////////////////////////////////  No Checking
		
		s = Time.realtimeSinceStartup;
		
		for (int i = 0; i < iterations; i++) {
			myVect.Normalize();
		}
		
		e = Time.realtimeSinceStartup;
		e -= s;
		
		Debug.Log("No Checking: "+e.ToString() + " seconds" );
		
		///////////////////////////////////////////// Checking
		
		s = Time.realtimeSinceStartup;
		
		Vector3 newVect = new Vector3(1,1,1);
		for (int i = 0; i < iterations; i++) {
			if (myVect.magnitude != 1) myVect.Normalize();
		}
		
		e = Time.realtimeSinceStartup;			
		e -= s;
		
		Debug.Log("Checking: "+e.ToString() + " seconds" );
		
		/////////////////////////////////////////////  No Checking (Vector3.normalized)
		
		s = Time.realtimeSinceStartup;
		
		for (int i = 0; i < iterations; i++) {
			vectToSet = myVect.normalized;
		}
		
		e = Time.realtimeSinceStartup;
		e -= s;
		
		Debug.Log("No Checking (Vector3.normalized): "+e.ToString() + " seconds" );
		
		///////////////////////////////////////////// Checking (Vector3.normalized)
		
		s = Time.realtimeSinceStartup;
		
		for (int i = 0; i < iterations; i++) {
			if (vectToSet.magnitude != 1) vectToSet = myVect.normalized;
		}
		
		e = Time.realtimeSinceStartup;			
		e -= s;
		
		Debug.Log("Checking (Vector3.normalized): "+e.ToString() + " seconds" );
		
	}
}

From decompiled UnityEngine.dll we have this:

public Vector3 normalized
{
	get
	{
		return Vector3.Normalize(this);
	}
}

Where Vector3.Normalize() methods are defined as:

public static Vector3 Normalize(Vector3 value)
{
	float num = Vector3.Magnitude(value);
	if (num > 1E-05f)
	{
		return value / num;
	}
	return Vector3.zero;
}
public void Normalize()
{
	float num = Vector3.Magnitude(this);
	if (num > 1E-05f)
	{
		this /= num;
	}
	else
	{
		this = Vector3.zero;
	}
}

Where Vector3.Magnitude() decompiled into:

public static float Magnitude(Vector3 a)
{
	return Mathf.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
}

And Vector3.magnitude has also the same Mathf.Sqrt() implementation:

public float magnitude
{
	get
	{
		return Mathf.Sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
	}
}

From the above decompiled codes it is obvious that the Vector3.Normalize() method does call the Vector3.Magnitude() method which uses Mathf.Sqrt(). So Unity does not check whether vector is already normalized or not.
Never use this:

if (myVect.magnitude != 1.0f) myVect.Normalize();

Because Vector3.Normalize() and Vector3.magnitude both calls Mathf.Sqrt() and calling Mathf.Sqrt() twice is awful. so use either this:

myVect.Normalize();

which you would call Mathf.Sqrt() just once.

Or this, depending on your choice:

if (myVect.sqrMagnitude != 1.0f) myVect.Normalize();

Above can be improved by using Mathf.Approximately() :

if (!Mathf.Approximately(myVect.sqrMagnitude, 1.0f)) myVect.Normalize();

A general rule for “check to skip this step” is to consider: 1) how often will the check save me time vs. waste time, 2) how cheap is the check compared to what I might skip.

For normalizing, the check will almost never save you time (how many random Vectors happen to be length 1?) and the time to check adds an extra maybe 10%(?) (sqrMagnitude is x*x+y*y+z*z, plus two compares for Approximate.)

If you have something taking two sources of Vectors: normalized and random, most people use two front ends: “DoStuff” and “DoStuffWithNormedVector,” where doStuff normalizes then calls the other one.

A quick update on this topic:
Unity now does the check:
public void Normalize()
{
float magnitude = this.magnitude;
if ((double) magnitude > 9.99999974737875E-06)
this = this / magnitude;
else
this = Vector2.zero;
}