Search Unity

Question Physics2D.Raycast Not Performing Expected Results?

Discussion in 'Physics' started by AlexHntk, Nov 4, 2023.

  1. AlexHntk

    AlexHntk

    Joined:
    May 6, 2015
    Posts:
    59
    Hey, I've got an annoying issue I can't seem to solve.

    I'm working on a script to raycast outwards and determine if an area is suitable to place a Node, to later be used as available Enemy Spawn locations.

    Code below:


    Code (CSharp):
    1.  
    2.  
    3.  void Awake()
    4.     {
    5.         spawnCreate = this;
    6.  
    7.  
    8.         newX = xPos_List[0]; // this is a list of the X positions for our "direction"
    9.         newY = yPos_List[0]; // this is a list of the Y positions for our "direction"
    10.         newNode_pos.Add(this.transform.position);
    11.         start_distance = distance;
    12.         direction = new Vector2(this.transform.position.x + newX, this.transform.position.y + newY);
    13.  
    14.         RaycastFind();
    15.     }
    16.  
    17.  
    18.  
    19.     public void RaycastFind()
    20.     {
    21.  
    22.  
    23.      
    24.  
    25.  
    26.      
    27.         RaycastHit2D hit = Physics2D.Raycast(this.transform.position, direction, distance, layers);
    28.      
    29.  
    30.      
    31.         if (hit.collider==null)
    32.         {
    33.          
    34.             Vector2 place = new Vector2(direction.x, direction.y);
    35.  
    36.             if (!newNode_pos.Contains(place))
    37.             {
    38.                 newNode_pos.Add(place);
    39.                 distance += distance_add;
    40.                 direction = new Vector2(this.transform.position.x + newX * distance, this.transform.position.y + newY * distance);
    41.                 RaycastFind();
    42.             }
    43.          
    44.          
    45.  
    46.         }
    47.         else if (hit.collider != null) // && hit.collider.CompareTag("Walls"))
    48.         {
    49.  
    50.  
    51.             if (i < (numberOfRays - 1)) // number of rays minus 1 to not exceed our List.Count for the X and Y direction variables, newX and newY respectively
    52.             {
    53.                 i++;
    54.                 newX = xPos_List[i];
    55.                 newY = yPos_List[i];
    56.                 distance = start_distance;
    57.                 direction = new Vector2(this.transform.position.x + newX * distance, this.transform.position.y + newY * distance);
    58.                 RaycastFind();
    59.                 print("Scanning");
    60.  
    61.             }
    62.             else if (i == (numberOfRays - 1))
    63.             {
    64.                 i = 0;
    65.                 newX = xPos_List[i];
    66.                 newY = yPos_List[i];
    67.                 distance = start_distance;
    68.                 direction = new Vector2(this.transform.position.x + newX * distance, this.transform.position.y + newY * distance);
    69.                 print("Reset");
    70.  
    71.                 //Finished Placing Nodes
    72.  
    73.             }
    74.  
    75.         }
    76.  
    77.  
    78.  
    79.  
    80.  
    81.  
    82.     }
    83.  
    84.  

    What I was hoping / expecting: We raycast out in a direction and if there is no collision, raycast once more but with additional distance. Repeat until we hit a Wall at which point the ray changes its direction and resets distance to check. Rinse and repeat until all 16 rays have been used.

    Instead I'm getting: image_2023-11-04_191258081.png
    The nodes are being place as desired in a gradual outward fashion but the rays are stopping at seemingly random places. I've tried this on an empty scene and gotten the same results (switched to a live scene because my Test Scene has a lot of annoying / tedious to remove Errors - completely unrelated to this script, I promise!).

    I'm not getting any errors with this, and I've tried debugging everywhere I can think of. Layer mask is set to the appropriate fields as well. One other odd thing is that int i is never reaching 16 (or returning to zero as in the last part of the else if).

    Any help greatly appreciated!
     
  2. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    1,742
    your layers, its a layermask.... you know thats different right?
     
  3. AlexHntk

    AlexHntk

    Joined:
    May 6, 2015
    Posts:
    59
    The layermask sets which layers the Raycast can detect on, no? I feel like this is how I've always used it ?
     
  4. AlexHntk

    AlexHntk

    Joined:
    May 6, 2015
    Posts:
    59
    To provide a bit more info too, the Raycast layer mask includes: Level, SoftWalls, Props.

    The object the Raycaster is on is set to the Player layer (which does physics interact with Level. Ive also tried setting it's layer to Level, just in case).

    The objects which are on the Level layer are all Tilemap colliders with Static Rigidbodies. I'm 99.9% certain in the other cases where I use raycasting, they have similar properties and things perform as expected.
     
  5. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    1,742
    It depends how you set the layermask :p if you did it in the inspector yes, if you do it in code you need 1 << (layer1 || layer2)
     
  6. AlexHntk

    AlexHntk

    Joined:
    May 6, 2015
    Posts:
    59
    Unfortunately this aint it, the layermask is only set via inspector and not touched otherwise
     
  7. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    1,742
    Well that rules out that set of issues but by calling it layers it makes it less clear was all
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,459
    You should take a look at the docs for API you're using: Raycast. The second argument "direction" states, "A vector representing the direction of the ray." which doesn't mean pass an absolute world position as you are. A "direction" in Vector terminology is a very specific thing.

    You do:
    Code (CSharp):
    1. direction = new Vector2(this.transform.position.x + newX, this.transform.position.y + newY);
    but a direction would be (note removing the redundant this):
    Code (CSharp):
    1. direction = new Vector2(newX - transform.position.x , newY - transform.position.y);
    If you have two positions though and take a look at the scripting reference, you'd see there's a Linecast (line segment). Just pass the start and end positions and it'll give you what you want.

    You can also simply perform an OverlapPoint if you only want to know if Collider exists at that spawn point. Maybe you do want a point anywhere from the start to the end though; thought I'd mention it.

    Any other problems you have are related to your logic.

    NOTE: Honestly, the code in your post needs editing as it's got a lot of redundant space in it and is missing key parts of the things you're discussing. I'm not sure if you consider that important because you know your code but to others you're trying to ask for help from, it is. ;) It distracted me from seeing the problem immediately.
     
    AlexHntk likes this.
  9. AlexHntk

    AlexHntk

    Joined:
    May 6, 2015
    Posts:
    59
    Thank you for this! Linecast ended up being the fix, working properly now!
     
    MelvMay likes this.