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

Resolved RaycastHit[] returns IndexOutOfRangeException (not a off by one situation)

Discussion in 'Scripting' started by solidp26, Feb 1, 2022.

  1. solidp26

    solidp26

    Joined:
    Nov 1, 2018
    Posts:
    20
    In this code i do a raycast that goes through everything, checking if the objects are inside a "enemy" layermsk. It goes fine, until the ray hits something other than enemy, then i get the IndexOutOfRangeException error.

    Exact line of code that produces the error is line 5 here.

    Here's the code:
    Code (CSharp):
    1. for (int i = 0; i < penetration; i++)
    2.             {
    3.                 RaycastHit[] hits = Physics.RaycastAll(camera.position, transform.forward, range, enemy);
    4.  
    5.                 if (hits[i].collider.transform.gameObject != null)
    6.                 {
    7.                     var e = hits[i].collider.transform.gameObject;
    8.  
    9.                     if (i > 0)
    10.                     {
    11.                         Damage(e, 1 - penetretionDamageDecrease * i);
    12.                     }
    13.                     else
    14.                     {
    15.                         Damage(e, 1);
    16.                     }
    17.  
    18.                 }
    19.             }
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,529
    Your code doesn't make sense. If you using RaycastAll, it'll create and return an array with the results. You want to iterate that array (the length of the array), not whatever "penetration" is.
     
  3. solidp26

    solidp26

    Joined:
    Nov 1, 2018
    Posts:
    20
    Yup, that was the solution.

    Code (CSharp):
    1. RaycastHit[] hits = Physics.RaycastAll(camera.position, transform.forward, hit.distance, enemy);
    2.  
    3.             enemiesLeftToHit = penetration;          
    4.  
    5.                 for (int i = 0; i < hits.Length; i++)
    6.                 {
    7.  
    8.                     if (enemiesLeftToHit > 0)
    9.                     {
    10.                         enemiesLeftToHit--;
    11.  
    12.                         var e = hits[i].collider.transform.gameObject;
    13.  
    14.                         if (i > 0)
    15.                         {
    16.                             Damage(e, 1 - penetretionDamageDecrease * i);
    17.                         }
    18.                         else
    19.                         {
    20.                             Damage(e, 1);
    21.                         }                                      
    22.                     }
    23.  
    24.                    
    25.                 }

    Penetration is used to determine how many of those enemies would actually get damaged
     
    MelvMay likes this.
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,529
    Glad you got it working.

    I would consider not using the 2D physics queries that have either the "All" or "NonAlloc" suffixes. The "All" one creates an array which then gets left to the garbage collector. If done a lot, this can cause a lot of performance issues such as stalls etc which visually ends up as stutters.

    Only use the 2D physics queries without the suffix so above, use Physics.Raycast. Look at the API and you'll overloads that allow you to pass in an array or more preferably, an existing List<T> for results. If you reuse this list, there'll be no waste and you'll get better performance.