Calculate a percentage of a distance between two points

I have 2 Vector3 points

I want to be able to calculate a percentage of a distance between the two points based off a percentage, for example

private Vector3 GetPoint(Vector3 posA, Vector3 posB, float percent){

//lets say percent = .35
//get the Vector3 location 35% through Point A and B

}

any ideas?

1454377--78857--$Untitled-1.jpg

They math isn’t complicated, but it can sometimes get a bit tricky. Thankfully, Unity has done most of it for you already. There are lots of great utility functions in Vector3, Quaternion, and Transform that you should probably look through to get an idea of what you can do.

For this, specifically:

// Calculate the distance
float distance = Vector3.distance(posA, posB);

// Scale the distance
distance = distance * percent;

// Calculate the difference vector
Vector3 difference = posB - posA;

// Normalize and scale the difference vector
difference = difference.normalized * distance;

// Translate the vector back to A 
return (posA + difference);

That is off the top of my head so I may have made some mistakes. Testing it is up to you. The general idea should be straightforward enough, and you shouldn’t have to do any complicated vector math yourself.

1 Like

What you’re asking for is called linear interpolation. If you want the point 35% of the way from A to B, then this is simply

Vector3.Lerp(A, B, 0.35)

See Vector3.Lerp in the scripting reference for more detail.

Cheers,

  • Joe
1 Like

JoeStrout nailed it. :slight_smile:

1 Like

Yes, well, there’s the easy way, but he’s only supposed to find that on his own by checking the docs like I told him to. The moral of the story is that there’s lots of great helper functions in Unity.

In this case I’m not sure that he’d have found it, as it doesn’t sound like he’d know to look for a “lerp” or an “interpolation function” to find the right thing in the docs.

A case in point is the huge number of people who use Lerp incorrectly, by doing things like shoving Time.deltaTime in as the interpolation factor.

Hey, I just did that the other day. :wink: It’s actually a legit thing to do, but it should probably be used like that rarely. There’s this idea that Lerp is some kind of magic coroutine or something, when it’s really just a very basic math function that almost doesn’t even need to be a function.

–Eric

Yes, thank you for all the replies

What if you wanted to go the other way around and get the percentage at the known third point.

Well there’s one problem with that, we don’t know if the 3 points are in line with each other. And what do we do if they aren’t in line with each other?

Lets call the 3rd point C, so in the image above, the ? is C.

So, one way we can do this is that we just assume the person calling the method did their best effort to have the 3 points on the same line. And what we will do is project C on A->B to ensure we only measure it in that space. So if they pass in a C that is far away from A and B and no where on the line defined by AB… then we’ll only measure the percentage along AB.

This is because a dot product is a scalar projection. It measures the length of one vector along the other (with its scale intact that is). If the other is a unit vector though, then it’s the absolute length of one on the other. It’s like if you said AB was an axis, how far along the axis are we. If that axis was say the x-axis, it’s how far along the x-axis we are.

So with that assumption we will dot AC on a unit vector in the direction of AB, and divide by |AB| (magnitude). Which will give us the percentage along AB that AC is.

public static float GetPercentageAlong(Vector3 a, Vector3 b, Vector3 c)
{
    var ab = b - a;
    var ac = c - a;
    return Vector3.Dot(ac, ab.normalized) / ab.magnitude;
}

Note though, we could do some simplification here. Dot product is defined as:

A dot B = (Ai * Bi + Aj * Bj + Ak * Bk)
[where i, j, and k, are the 3 parts of the vector x, y, and z respectively]

And that normalized would just make it:

(Ai * Bi / |B| + Aj * Bj / |B| + Ak * Bk / |B|) / |B|

And if we distribute that in we get:

(Ai * Bi + Aj * Bj + Ak * Bk) / |B|^2

We can get rid of that square root for magnitude now!

public static float GetPercentageAlong(Vector3 a, Vector3 b, Vector3 c)
{
    var ab = b - a;
    var ac = c - a;
    return Vector3.Dot(ac, ab) / ab.sqrMagnitude;
}
4 Likes

Alternately you can just divide the distances:

    float percentDistAlong = Vector3.Distance(a,c)/Vector3.Distance(a,b);
1 Like

That is another method, but doesn’t consider the possibility that the point is way off from A and B. If you have points <0,0>, <5,0> and <0, 5>… is <5,0> really 100% of <0,5>?

Where as if you project with dot product, you’d get 0%.

Which is right though? That’s up to you to decide which one comes with the result you want.

Totally. Presumably if you want to know the percent along a path, you would hopefully know that that object is on the path in the first place (or you mix in direction to ensure that c is indeed on same angle as the angle between a &b). Both can be wrong. 0% in the above would seem to indicate that it is at point A. But, if you are trying to find out if something has completed the path, dividing distances can yield a false positive, as you pointed out.