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. Dismiss Notice

Find horizontal vector

Discussion in 'Scripting' started by FuzzyBalls, Aug 2, 2014.

  1. FuzzyBalls

    FuzzyBalls

    Joined:
    Jun 12, 2014
    Posts:
    47
    Hey,

    Iv'e run into a little trouble. I could use the help of someone's awesome brain.

    Basically I have a array of Vectors, they are a Vector2 array; this array is a array of objects converted from world space to screen space. What I'm trying to do (and failing) is get the index of the array horizontal to one of the items in the array I specify. Here's a couple images to help you visualise my concept.





    the objects in the scene move, so the screen space vector also changes. I have already done the logic to get its vector on screen. Thats the easy part.

    The circles in my images represent the screen space vectors on screen. The arrow pointing from myArray is what I'm trying to find.

    So say I want the vector in the horizontal direction of myArray[index to use] what would I need to do?
    Think of it as Raycasting down from the specified vector.


    Any ideas?
     
  2. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    You just need to loop through the array and pick the one with the X closest to yours. Here's some pseudo code:

    Code (csharp):
    1.  
    2. float startX = myArray[baseIndex].x;
    3. int closestIndex = -1;
    4. int closestXDelta = float.MaxValue;
    5. for(int i = 0; i < myArray.Length; ++i)
    6. {
    7.     xDelta = startX - myArray[i].x;
    8.     if(i != baseIndex && xDelta < closestXDelta)
    9.     {
    10.         closestIndex = i;
    11.         closestXDelta = xDelta;
    12.     {
    13. }
    14.  
     
  3. FuzzyBalls

    FuzzyBalls

    Joined:
    Jun 12, 2014
    Posts:
    47
    Hey man, Thanks for the reply. I appreciate it. But it doesn't work, or I'm doing something wrong.

    Quick note, I'm really stupid. I meant I need to find the vertical vector. NOT horizontal :p wow I'm stupid. I changed it to do your pseudo code with the y value tho but it still doesn't work

    Take a look at this screen grab:


    So I'm using index 10, and it's returning index 3 as its opposite vertical vector. When it should return 1 or 2. And it returns 3 for all index' I try.

    Here's my code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Test : MonoBehaviour {
    5.    
    6.     public GameObject[] gos;
    7.     public Vector2 horizontalDownPoint;
    8.     public Vector2[] screenPoints;
    9.     public int index;
    10.     private float yDelta;
    11.    
    12.     void Start () {
    13.         screenPoints = new Vector2[gos.Length];  
    14.     }
    15.    
    16.     void Update () {
    17.         index = Mathf.Clamp(index, 0, gos.Length - 1);
    18.        
    19.         float startY = screenPoints[index].y;
    20.         int closestIndex = -1;
    21.         float closestYDelta = float.MaxValue;
    22.        
    23.         for(int i = 0; i < screenPoints.Length; ++i) {
    24.             yDelta = startY - screenPoints[i].y;
    25.             if(i != index && yDelta < closestYDelta) {
    26.                 closestIndex = i;
    27.                 horizontalDownPoint = screenPoints[closestIndex];
    28.                 closestYDelta = yDelta;
    29.             }
    30.         }
    31.     }
    32.    
    33.     void OnDrawGizmos () {
    34.         for(int i = 0; i < gos.Length; i++)
    35.             Gizmos.DrawWireCube(gos[i].transform.position, Vector3.one);
    36.     }
    37.    
    38.     void OnGUI () {
    39.         GUI.Box(new Rect(horizontalDownPoint.x, horizontalDownPoint.y, 25, 25), "");
    40.        
    41.         for(int i = 0; i < gos.Length; i++) {
    42.             Vector3 screenPoint = Camera.main.WorldToScreenPoint(gos[i].transform.position);
    43.             screenPoint.y =  Screen.height - screenPoint.y;
    44.            
    45.             GUI.Box(new Rect(screenPoint.x, screenPoint.y, 20, 20), i.ToString ());
    46.             GUI.Label(new Rect(10, i * 13, 400, 70), i + " : " + GUIUtility.ScreenToGUIPoint(new Vector2(screenPoint.x, screenPoint.y)).ToString ());
    47.             screenPoints[i] = new Vector2(screenPoint.x, screenPoint.y);
    48.         }
    49.     }
    50. }
    51.  
     
  4. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Use a Mathf.Abs around the deltaY computation. Thats a bug in my original code.
     
  5. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Also, once you have the two points the vec between is just endPoint - startPoint.
     
  6. FuzzyBalls

    FuzzyBalls

    Joined:
    Jun 12, 2014
    Posts:
    47
    Hey,

    Still can't get this working.. Am I doing something wrong?

    Code (CSharp):
    1.  
    2.         float startY = screenPoints[index].y;
    3.         int closestIndex = -1;
    4.         float closestYDelta = float.MaxValue;
    5.      
    6.         for(int i = 0; i < screenPoints.Length; ++i) {
    7.             yDelta = Mathf.Abs(startY - screenPoints[i].y);
    8.          
    9.             if(i != index && yDelta < closestYDelta) {
    10.                 closestIndex = i;
    11.                 Vector2 downPoint = screenPoints[closestIndex];
    12.                 horizontalDownPoint = downPoint - screenPoints[index];
    13.                 closestYDelta = yDelta;
    14.             }
    15.         }
    currently if I input index 10 it gives me a vector in the top left of the screen. No where near the vector I need
     
  7. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    If I do this for you I'm not really helping you learn. You should take the time to work it out yourself. Draw the algorithm on paper, print out values, and read up more on how vectors work. You're close and just need to think it through the rest of the way; it's how you get better.
     
  8. FuzzyBalls

    FuzzyBalls

    Joined:
    Jun 12, 2014
    Posts:
    47
    I completely agree, I never expect someone to do something for me. I never even copy and paste directly. I write it out myself so it's imprinted in my memory

    You say I'm close. But what am I missing? I have a basic understanding of vector mathematics, the point of this exercise is for me to extend my knowledge.
     
  9. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Here are a few hints:

    Verify that you understand your coordinate system. If this is screen space, is Y up or to the side? If you want the point below another point, is that the one with the least vertical distance or least horizontal distance?

    For vector math, understand the difference between a point and a direction. Check out the thread in Learning about 3d math. I posted there and there are some great links. It's mostly relevant to 2D math as well.
     
  10. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Also, learn how to use the debugger to make sure the code is doing what you think its doing. I didnt test my code, its just to convey the idea. Maybe there is a bug there!
     
  11. crag

    crag

    Joined:
    Dec 13, 2013
    Posts:
    145
    I assume you finished this issue, if not, here is some pseudocode:
    Code (CSharp):
    1. int useIndex = 0;                // element in vector array we are checking against
    2. float diff = 0.0;                    // distance in 3D space
    3. float smallestDiff = 1000.0;            // prepopulate with some impossibly high value
    4. float angle = 0.0;                // vector between selected points
    5. Vector3 checkPoint;                // temporary vector3 point to evaluate with start point
    6. Vector3 startPoint = screenPoints[index];    // the point you are evaluating
    7.  
    8. for (int i = 0; i < screenPoints.Length; ++i)
    9. {
    10.     if (i != index)
    11.     {
    12.         checkPoint = screenPoints[index];
    13.         diff = Mathf.Abs(startPoint.x - checkPoint.x);
    14.  
    15.         if (diff < smallestDiff)
    16.         {
    17.             useIndex = i;
    18.             smallestDiff = diff;
    19.         }
    20.     }
    21. }
    22.  
    23. angle = Vector3.Angle(startPoint - screenPoints[useIndex]);
     
    FuzzyBalls likes this.
  12. FuzzyBalls

    FuzzyBalls

    Joined:
    Jun 12, 2014
    Posts:
    47
    Thanks dude, Yeah I managed to figure it out in the end. Your method works a little different to mine tho so I'll definitely check yours out