Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

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

Discussion in 'Scripting' started by asperatology, Aug 8, 2015.

  1. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981


    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:

    Code (CSharp):
    1. private float getInnerRadius(GameObject obj) {
    2.     Renderer renderer = obj.GetComponent<Renderer>();
    3.     return getInnerRadius(obj.transform.position, renderer.bounds.size);
    4. }
    5.  
    6. private float getInnerRadius(Vector3 origin, Vector3 size) {
    7.     return Vector3.Distance(origin, origin + (size / 2f));
    8. }
    Because the unit's radius will grow over time, it's not always constant.

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



    4. Subtract the green line's length with the radius given. (I'm sure it is going to be used in some way)
    5. 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.
     
    Last edited: Aug 9, 2015
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    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?
     
  3. William_Lee_Sims

    William_Lee_Sims

    Joined:
    Oct 11, 2014
    Posts:
    40
    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!
     
  4. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    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?
     
  5. William_Lee_Sims

    William_Lee_Sims

    Joined:
    Oct 11, 2014
    Posts:
    40
    With your distance being 2.5 units, you'll want something more like "R.position - (R.radius + 2.5) * normalizedVector".
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    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:

    Code (csharp):
    1.  
    2. Transform obj1; //this is object with radius R
    3. Transform obj2; //this is object with radius S
    4.  
    5. var r = getInnerRadius(obj1.gameObject);
    6. var s = getInnerRadius(obj2.gameObject);
    7.  
    8. var origin = obj1.position; //a position our vectors will be based off
    9. var v = obj.position - origin; //a vector from obj1 to obj2
    10. var totalLen = v.magnitude; //length of green line
    11. var innerLen = totalLen - r - s; //length along green from edge of obj1 to edge of obj2
    12. v.Normalize();
    13.  
    14. Vector3 redx;
    15. if (innerLen < 0f)
    16. {
    17.     //the two objects are so close their bounds are overlapping...
    18.     //I guess we could pick the point averaged between this empty distance?
    19.     //it will still be a point inside the bounds of both... since they overlap
    20.     var avg = Mathf.Abs(r - s) / 2f;
    21.     red = origin + v * (r - avg);
    22. }
    23. else if (innerLen == 0f)
    24. {
    25.     //the two objects are touching each others bounds... the only point between them is this point
    26.     redx = origin + v * r;
    27. }
    28. else
    29. {
    30.     //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
    31.     redx = ????;
    32. }
    33.  
    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:

    Code (csharp):
    1.  
    2. Transform obj1; //this is object with radius R
    3. Transform obj2; //this is object with radius S
    4.  
    5. var r = getInnerRadius(obj1.gameObject);
    6. var s = getInnerRadius(obj2.gameObject);
    7.  
    8. var dist = (obj2.position - obj1.position).magnitude - s;
    9. if (dist <= range)
    10. {
    11.     //we can successfully shoot
    12. }
    13.  
     
  7. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I'm sorry for not updating the first post. It is now updated. X is located 2.5 Unity units away from the unit.
     
  8. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    asperatology likes this.
  9. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Oh wow, that seems even easier...
     
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    2.5 units from the edge of the unit?

    Code (csharp):
    1.  
    2. Transform obj1; //this is object with radius R
    3. Transform obj2; //this is object with radius S
    4.  
    5. var r = getInnerRadius(obj1.gameObject);
    6. var range = 2.5f;
    7.  
    8. var v = obj2.position - obj1.position;
    9. var redx = obj1.position + v.normalized * (range + r);
    10.  
    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.
     
  11. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Thank you. I guess I really did think too much. I need a break.
     
  12. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    something like this may be a easy solution.
    Code (CSharp):
    1. Vector3 dir = p1 - p2;
    2. Ray ray = new Ray(p1, dir);
    3. Vector3 pointOnRay = ray.GetPoint(2.5f);