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

Vector2.Distance doesn't return same result as Raycasthit2D?

Discussion in 'Scripting' started by Punfish, Jan 1, 2015.

  1. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    327
    I'm gathering the Vector2.Distance from ObjectA to ObjectB, then casting a ray2d from ObjectA to ObjectB using that distance to determine if anything is in the way. What's unusual is that not only is the ray hitting an object(which does not exist) but it's hitting an object prior to the actual distance between ObjectA and ObjectB.
    Below is the code I'm using to better show the situation.

    Getting the location to move/cast to
    Code (csharp):
    1.  
    2.   //manually set the mouse position to a vector3
    3.   Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
    4.   //set world destination)
    5.   Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition);
    6.   Vector2 flatWorldPosition = new Vector2(worldPosition.x, worldPosition.y);
    7.   RoundVector2ToGrid(ref flatWorldPosition);
    8.   //after rounding to nearest tile set move destination.
    9.   _move.Destination = flatWorldPosition;
    10.   //find the best way to reach this destination
    11.   FindPath(flatWorldPosition);
    12.  
    Checking for collision using raycast
    Code (csharp):
    1.  
    2. private void FindPath(Vector2 destination)
    3.     {
    4. //this is a test object without a collider that is moved to my Vector2 destination.
    5. //it appears to be placed properly. used for testing
    6.   GameObject testObj = GameObject.FindGameObjectWithTag("Finish");
    7.   testObj.transform.position = destination;
    8.  
    9.         RaycastHit2D hit;
    10.         //get current position of object
    11.         Vector2 objectPosition = new Vector2(transform.position.x, transform.position.y);
    12.         //starting position of ray and max cast distance
    13.         Vector2 rayStart;
    14.         float castDistance;
    15.         float quickestPath = -1f;
    16.  
    17.         //first check if the object can reach its destination without any way points
    18.         rayStart = objectPosition;
    19.         //distance between obj and final dest
    20.         castDistance = Vector2.Distance(rayStart, destination);
    21.         //fire ray
    22.         hit = Physics2D.Raycast(rayStart, destination, castDistance);
    23.         //if we dont hit anything then its a clean shot to the final destination.
    24.         //set move location and get out of method
    25.         if (hit.distance == 0)
    26.         {
    27.       //for some reason hit.distance is always > 0 even with no obstacles in the way.
    28. //hit.distance is < than castDistance
    29.  

    Don't suppose I'm missing something here?
     
    Last edited: Jan 1, 2015
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    1) FindGameObejctWithTag is slow, you should cache that into a field/property somewhere, so you're not constantly calling that function.

    2) The RaycastHit2D that comes back from Physics2D.Raycast should have a reference to the collider, transform, and rigidbody of whatever it hit... check what it hit. Just print it out or something.
     
  3. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    327
    1) is just for testing to see where I'm clicking.

    2) I tried this but I was just getting the name of the component eg: Collider2D. What method would I use to get the GameObjects name that the collider belongs to?
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    hit.collider.gameObject.name


    Also, the cache would be super simple:

    Code (csharp):
    1.  
    2. private GameObject _testObj;
    3. private void FindPath(Vector2 destination)
    4. {
    5.     if(_testObj == null) _testObj = GameObject.FindGameObjectWithTag("Finish");
    6. ...
     
  5. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
    Its because hit distance is the distance to the point in space where you collide with a given collider. Not the collider objects position which you are using in your distance check
     
  6. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    327
    I believe I found the problem, but I'm not sure how to fix it.

    On line 22 I'm casting to my destination, which is where I want my object to move to. However, the ray is not casting in that direction, it seems to be casting in a completely different direction. So I'm assuming that the 'direction' variable in raycast isn't the literal sense of position of where you wish the ray to go but rather an angle.

    For example, let's say I want to move to 65, -65 -- and let's pretend my character is at 75, -75. My characters pathing would be from SE moving to NE, but some reason when I use 65, -65 from my characters location as the Raycast direction its casting southish. Even when I use Debug.DrawLine it's showing a line going to the proper location, but Raycast still doesn't seem to get the hint.
     
  7. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Raycast takes a STARPOS and a DIRECTION
    You are giving it start and DESTINATION
    which is wrong

    You could try linecast for that
     
    Punfish likes this.
  8. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    327
    That might work. The documentation states there is no way to limit how far the line will cast. I suppose the best way to compare a hit would be if (linecastHit < objectDIstance) then hit = true?

    That did the trick! Wasn't aware that existed. Thank you!
     
    Last edited: Jan 2, 2015