I was playing around, having fun, creating my own vector class, and the need to normalize it arose, I wrote a property and a function, the same as Unity, then I printed the result in the console and compared it with a vector with the same values but normalized by Unity’s functions, the numbers were off, my result threw something similar to 0.707, while Unity’s threw a rounded 0.71, for the value X of both vectors.
At first, I thought Unity was using fast inverse square root, so I tried that out, and the result was off again and by much more than the first time.
Here’s the code for the inverted square root:
float InvSqrt(float x)
{
float xhalf = 0.5f * x;
int i = BitConverter.SingleToInt32Bits(x);
i = 0x5f3759df - (i >> 1);
x = BitConverter.Int32BitsToSingle(i);
x = x * (1.5f - xhalf * x * x);
return x;
}
What really caught my eye is that there’s a warning in Unity’s API on the Vector.magnitude page that says that you should use sqrMagnitude instead since magnitude uses a square root operation, yet there’s no warning on the normalize or Normalized pages.
Does anyone have any idea how Unity normalizes vectors, or if there is a way to normalize a vector without using a square root? I wasn’t able to find anything on the net, and I’ve been searching for 3 hours or so.
You’ll find that a lot of the math based functions in Unity are fairly simple wrappers of the fuctions found in the Math library. The big difference between the Math library and the Mathf library is that Math library generally works with doubles and Unity.Mathf casts the results to a float. This can introduce some floating-point errors but it’s usually not that noticeable.
It’s also worth noting that the fast inverse square root algorithm isn’t actually all that fast on modern processors (a lot has changed since '96). It’s also not 100% on accuracy, so you may see some errors creeping in unexpectedly (it’s got an error margin of around 0.175%).
Honestly, the sqrt operation isn’t all that slow these days and unless you’re trying to edge out every ounce of performance there are far bigger things in your code that you could probably optimize first. Calling magnitude every frame is pretty wasteful if sqrMagnitide would also do the job but, if you’re calling it fairly infrequently, then there’s really no need to worry about it.
If you really need the inverse square root for something then you could always use the rsqrt() method from the Mathematics library, which is optimised for modern hardware.
This is what bothered me about normalizing vectors, the calculation uses the magnitude of the vector and there’s no way to use sqrMagnitude instead as far as I’m aware, but no one ever talks about it, I suppose it’s because of what you said, it’s not really that much of a worry, even if I’m calling it during each update tick.