How to obtain a Vector3 at this position marked at the red X? (Infographic)

I’m building a simple 3D RTS attack range, in which the unit (black circle) will start to attack when the other unit is within range (about 2.5 Unity units away from the edge of the unit’s circle).

However, the unit’s radius will grow depending on the player’s decision.

I need to find a way how to obtain the Vector3 position marked with a red X in the picture given above.

This is what I sort of come up with, and I need some help in determining the results.

  1. I first calculate the distance between the two units. (Green line’s length)
  2. I then calculate the radius of the game object unit using this:
private float getInnerRadius(GameObject obj) {
    Renderer renderer = obj.GetComponent<Renderer>();
    return getInnerRadius(obj.transform.position, renderer.bounds.size);
}

private float getInnerRadius(Vector3 origin, Vector3 size) {
    return Vector3.Distance(origin, origin + (size / 2f));
}

Because the unit’s radius will grow over time, it’s not always constant.

  1. After obtaining the radius of a unit, I need to do a scalar projection to obtain a Vector3 position pointed by this indigo arrow:

  1. Subtract the green line’s length with the radius given. (I’m sure it is going to be used in some way)
  2. And then this is the part where I am stuck at, given that the red X can be anywhere in between the following highlighted area:

It’s kind of hard to figure it out. I do know that I may be able to determine the red Xs using NavMeshAgent’s stoppingDistance, but I’m not sure how to utilize that.

If anyone can provide clues, I would be so happy! If there is a more optimal way of doing this, please do let me know.

Thanks in advance.

You’ve told us everything except that which we need to help you: What defines where the red X is? Is it a fixed, let’s say 5 units, away from the edge of the target circle? Is it 125% of the radius? Is it some percentage of the distance between the two objects? What, exactly, defines where the red X goes?

Probably the easiest way to do this is to test your distance (or distance squared) continuously in the Update function. That way if it changes along the way, you’ll do it at the exact moment they match.

If you really need to do it with math, it’s not that hard. First convert the line to a unit vector. That will give you “1 unit” in the direction of the line. Like “(S.position - R.position).normalized()”. You can subtract that normalized vector times the sum of the radiuses of “R” and “S” from the position of “R” and you’ll have a stopping point. Like “R.position - (R.radius + S.radius) * normalizedVector”.

Let me know if you have any questions!

Right, I forgot about that. Sorry. The distance between the red X and the edge of the attackee’s circle is about 2.5 Unity units long. (Attackee is the one being attacked, the attacker is the one hitting the attackee).

I should try that and will respond back. Seems to be much more optimized than what I have, with the scalar projection and whatnots.

May I ask why we need to get the sum of the radius of both R and S?

With your distance being 2.5 units, you’ll want something more like “R.position - (R.radius + 2.5) * normalizedVector”.

What is your red x?

It’s arbitrary in your image. All I see is a red x somewhere between to objects on a green line.

There’s numerous amount of positions there (technically infinite). Which one you want?

Lets start here:

Transform obj1; //this is object with radius R
Transform obj2; //this is object with radius S

var r = getInnerRadius(obj1.gameObject);
var s = getInnerRadius(obj2.gameObject);

var origin = obj1.position; //a position our vectors will be based off
var v = obj.position - origin; //a vector from obj1 to obj2
var totalLen = v.magnitude; //length of green line
var innerLen = totalLen - r - s; //length along green from edge of obj1 to edge of obj2
v.Normalize();

Vector3 redx;
if (innerLen < 0f)
{
    //the two objects are so close their bounds are overlapping...
    //I guess we could pick the point averaged between this empty distance?
    //it will still be a point inside the bounds of both... since they overlap
    var avg = Mathf.Abs(r - s) / 2f;
    red = origin + v * (r - avg);
}
else if (innerLen == 0f)
{
    //the two objects are touching each others bounds... the only point between them is this point
    redx = origin + v * r;
}
else
{
    //so we have this gap between them... WHERE on the gap are you looking for??? You haven't defined redx beyond being between the 2
    redx = ????;
}

This last part here doesn’t make sense. What IS redx beyond it being between obj1 and obj2? You don’t define it any more specifically than that.

What are you going to use this redx for anyways?

You talk about ‘range’, are you testing if obj2 is in range of obj1?

Are you going to see if obj2 is in range of obj1? Why do you need to find redx then?

What you need to just do is test if the range from the turret position of obj1 towards obj2 is less than the max range of the turret. If the turret position (the point the ‘range’ is defined from) is ‘range’, then we don’t care about obj1’s radius (as it’s doesn’t alter the range). All we care about is obj2’s position. If we say that obj1’s turret position is obj1’s position. Then it’d just be:

Transform obj1; //this is object with radius R
Transform obj2; //this is object with radius S

var r = getInnerRadius(obj1.gameObject);
var s = getInnerRadius(obj2.gameObject);

var dist = (obj2.position - obj1.position).magnitude - s;
if (dist <= range)
{
    //we can successfully shoot
}

I’m sorry for not updating the first post. It is now updated. X is located 2.5 Unity units away from the unit.

You could make a Ray object, by providing the origin point and a direction than simply use its GetPoint Method to get a point on the ray x distance away.

1 Like

Oh wow, that seems even easier…

2.5 units from the edge of the unit?

Transform obj1; //this is object with radius R
Transform obj2; //this is object with radius S

var r = getInnerRadius(obj1.gameObject);
var range = 2.5f;

var v = obj2.position - obj1.position;
var redx = obj1.position + v.normalized * (range + r);

it’s the units position, plus a vector in the direction of the other unit (v.normalized), that is of length the range (2.5) + its radius.

You don’t even need the other units radius for anything.

Thank you. I guess I really did think too much. I need a break.

something like this may be a easy solution.

Vector3 dir = p1 - p2;
Ray ray = new Ray(p1, dir);
Vector3 pointOnRay = ray.GetPoint(2.5f);