Normalized vector added to vector returning NaN

I’m trying to create some simple targetting AI, but for whatever reason, the second I add the normalized vector to my position, it returns NaN. If I remove the last line, it returns the expected normalized vector. Thanks. Here’s my code:

        switch (behavior)
        {
            case 0:
                target = Main.mouse.Position.ToVector2();
                direction = Vector2.Normalize(target - position);
                break;
        }
        position += direction;

Hey when this happens, try checking the values in target and position. I have a sneaking suspicion that this happens when target and position are the same.

When you normalize the vector, you divide each component (x and y) by the length. If they’re the same position, the length will be zero. Maybe this results in a NaN value instead of a divide by zero exception?

Worth a look :wink:

Huh, that makes sense, but I tried it out and they’re definitely not the same.

What values are they, immediately prior to the call to Vector2.Normalize?

The position starts out at Vector2.Zero, and the target starts out as the mouse’s position.

I was hoping you’d give me numbers that you pulled from your debug window, right before it normalized to NaN.

Just in case you’re not familiar with it and are using Visual Studio, press F9 on the line you want it to break at. I think if you compare x or y to NaN in some kind of if statement, you can set your breakpoint there and see the exact values of target and position at the point where direction evaluates to NaN. Something like this…

        switch (behavior)
        {
            case 0:
                target = Main.mouse.Position.ToVector2();
                direction = Vector2.Normalize(target - position);
                if (direction.X == Single.NaN || direction.Y == Single.NaN)
                {
                        Debug.WriteLine("Setting breakpoint here!"); // Alternatively just output the variables to the console :D
                }
                break;
        }
        position += direction;

The reason I ask is that if we know the exact values, we can then do some experiments to see if we can reproduce the behaviour, or work to better understand the result you’re seeing.

NOTE: I did some googling and I think you can compare to Single.NaN, but I’ve never actually done that comparison so you might want to look into it if that doesn’t work :wink:

1 Like

Strange. Both x == nan and y == nan return false. Even stranger, when I output direction to the console whithout adding it to the position, it gives me the expected normalized vector.

        switch (behavior)
        {
            case 0:
                target = Main.mouse.Position.ToVector2();
                direction = Vector2.Normalize(target - position);
                Console.WriteLine(direction);
                break;
        }

it says direction is {X:-0.3437619 Y:0.9390568} and it is definitely the right value. It stops changing when I stop moving my mouse, and just seems like the right value.

EDIT: If I change the value of target to Vector2.One, Normalize() returns {X:0.7071068 Y:0.7071068}
which leads me to believe the problem is with the target somehow.

you should use Single.IsNan https://docs.microsoft.com/en-us/dotnet/api/system.single.isnan?view=netcore-3.1

1 Like

Thanks, KakCAT! Maybe give that a try in your comparisons.

My spidey senses are still tingling here. From what I see of your code, you are making a point chase a target. In this case, it’s your mouse cursor. When those two are not the same point, you calculate the direction to that point and, I assume, then move the point some amount along that direction vector.

However, I don’t see anything that handles the case when the point arrives at the target. When this happens, the distance between the two will become zero and your direction would, predictably, become {NaN,NaN}.

This is reinforced by you saying that you’re observing valid values of direction. So what’s key here is to identify when your direction turns into the value you don’t want, and what the values going into its calculation are.

Truth be told, I would have expected direction.X == Single.NaN to work since there wouldn’t be any need to worry about floating point error, but I’ve been wrong before! Give the same comparison but use KakCAT’s suggestion of Single.IsNan(…) a try and see if you can hit your breakpoint that way :slight_smile:

*Edit: I did my own confirmation. KakCAT is totally correct. You have to use IsNaN. My own breakpoint doesn’t get hit when I do the equality comparison. Because reasons, I guess. Anyway, that should let you hit your breakpoint and better see what’s going on there.

from msdn:

Use the IsNaN method to determine whether a value is not a number. In general, Single operators cannot be used to compare Single.NaN with other Single values, although comparison methods (such as Equals and CompareTo) can

That’s why “==” doesn’t work. Anyway. Trinith already said it: You need any sort of mechanism to react when the target is reached, as you never can normalize a Vector which is of zero length. It will get NaN and every operation you do with that NaN will result just in another NaN (which sometimes can make it hard to find the actual source of the culprit)

1 Like

Hey thanks for posting that about == :slight_smile:

Something that I’m curious about… I’ve always been under the expectation that .Equals and == should have equivalent functionality. Indeed, when I implement both of those, I use one to drive the other.

Is this something not universally employed, or is my understanding incorrect?

for object types “==” is a substitute for ReferenceEquals while .Equals is just a virtual method (normally comparing the equality. String is an exception, where “==” actually compares the contents.

for built in value types “==” compares the value.

The problem is more logically … NaN (Not A Number) is just not a number - so it can never be compared to a number, as it is non. So in that case every operator comparison with NaN will always fail (return false).

You can actually just use

if( t != t )

if t is NaN this returns true (but will produce a warning. It’s possible that the above is exactly what is used in the IsNaN Function, but I am not sure - there is even a much faster way with bitfields but I have it not at hand currently.

Thanks for the clarifications.

For many, many years now, when I overload == on an object, I implement it to test for equality. Perhaps I should revisit this strategy, or at least do some more research.

normalizing a vector2 near a min or almost a zero value has a good chance to produce a nan.
while a divide by zero is illegal dividing into zero is undefined as well as dividing a value more then min value into a min value.

// when a b is near min value.
c2 = x*x + y*y;
c = squareroot(c2);
// theta's.
x / c = sinx;
y / c = cosy;

if target - position’s resulting x + y is very small or typically less then 1 in this case you already know there will be contact they are inside each other.

In most scenarios this situation can simply be disallowed however when the mouse is the target the user can put his cursor over the position or near enough to cause a nan so you need the extra check.

1 Like

Thanks. I figured out the problem and it was actually with the mouse. The target and the character colliding wasn’t the problem btw, because it was giving me NaN every update, way before they were any close to each other.

What was the problem? I’m curious! :slight_smile: