Search Unity

How can I make this code more readable?

Discussion in 'Scripting' started by AV_Corey, Nov 10, 2017.

  1. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    Every now and then I have a group of code that has one very slight difference such as an incremental number (hit1/hit2/hit3) and it ends up taking up a lot of space. It doesn't look great and isn't very readable. How can I shorten these groups of code down and make them look prettier?

    Here is an example:

    Code (CSharp):
    1.        
    2.         Debug.DrawRay(groundedRay1.transform.position, Vector2.down * 0.1f, Color.green);
    3.         RaycastHit2D hit1 = Physics2D.Raycast(groundedRay1.transform.position, -Vector2.up, 0.1f);
    4.         Debug.DrawRay(groundedRay2.transform.position, Vector2.down * 0.1f, Color.green);
    5.         RaycastHit2D hit2 = Physics2D.Raycast(groundedRay2.transform.position, -Vector2.up, 0.1f);
    6.         Debug.DrawRay(groundedRay3.transform.position, Vector2.down * 0.1f, Color.green);
    7.         RaycastHit2D hit3 = Physics2D.Raycast(groundedRay3.transform.position, -Vector2.up, 0.1f);
    8.  
    9.         if (hit1.collider != null) {
    10.             if (hit1.collider.gameObject.layer == 8) { //If touching the 'Ground' layer.
    11.                 grounded1 = true;
    12.             }
    13.             else {
    14.                 grounded1 = false;
    15.             }
    16.         }
    17.         else {
    18.             grounded1 = false;
    19.         }
    20.  
    21.         if (hit2.collider != null) {
    22.             if (hit2.collider.gameObject.layer == 8) { //If touching the 'Ground' layer.
    23.                 grounded2 = true;
    24.             }
    25.             else {
    26.                 grounded2 = false;
    27.             }
    28.         }
    29.         else {
    30.             grounded2 = false;
    31.         }
    32.  
    33.         if (hit3.collider != null) {
    34.             if (hit3.collider.gameObject.layer == 8) { //If touching the 'Ground' layer.
    35.                 grounded3 = true;
    36.             }
    37.             else {
    38.                 grounded3 = false;
    39.             }
    40.         }
    41.         else {
    42.             grounded3 = false;
    43.         }
    44.  
     
  2. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    You can use Arrays to store these. You can simply iterate like so:
    Code (CSharp):
    1. for (int i = 0; i < objectCount; i++)
    2. {
    3.     if (hit[i].collider != null) {
    4.     if (hit[i].collider.gameObject.layer == 8) { //If touching the 'Ground' layer.
    5.         grounded[i] = true;
    6.     }
    7.     else {
    8.         grounded[i] = false;
    9.     }
    10.     }
    11.     else {
    12.         grounded[i] = false;
    13.     }
    14. }
    Often it makes sense to store things in a struct or class instead of using multiple arrays:
    Code (CSharp):
    1. public class MyObject
    2. {
    3.     public bool grounded;
    4.     public Transform hit;
    5. }
    6. [SerializeField] MyObject[] myobjects;
    7. for (int i = 0; i < myobjects.Length; i++)
    8. {
    9.     var obj = myobjects[i];
    10.     if (obj.hit.collider != null) {
    11.     if (obj.hit.collider.gameObject.layer == 8) { //If touching the 'Ground' layer.
    12.         obj.grounded = true;
    13.     }
    14.     else {
    15.         obj.grounded = false;
    16.     }
    17.     }
    18.     else {
    19.         obj.grounded = false;
    20.     }
    21. }
     
  3. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    Ofcourse, not sure why I did not think of that. Thank you very much :)
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Or if it is too specific to be an array, you can just turn it into a method, which in this case takes in a position and returns a bool. Turns it into something very short. It's up to your own taste whether you find that last line readable or not. You can easily expand that back into an if statement.
    Code (csharp):
    1.  
    2. grounded1 = MyRaycastMethod(groundedRay1.transform.position);
    3. grounded2 = MyRaycastMethod(groundedRay2.transform.position);
    4. grounded3 = MyRaycastMethod(groundedRay3.transform.position);
    5.  
    6. private bool MyRaycastMethod(Vector3 position, float distance = 0.1f, int layer = 8)
    7. {
    8.   Debug.DrawRay(position, Vector2.down * distance, Color.green);
    9.   RaycastHit2D hit = Physics2D.Raycast(position, Vector2.down, distance);
    10.   return (hit.collider != null) && (hit.collider.gameObject.layer == layer);
    11. }
    12.  
     
    Last edited: Nov 10, 2017
    AV_Corey likes this.
  5. nat42

    nat42

    Joined:
    Jun 10, 2017
    Posts:
    353
    Suggest replacing the magic number "8" with a constant, more readable and if you're ground layer every needs to change or much easier to update/find
    Code (CSharp):
    1.     if (obj.hit.collider.gameObject.layer == groundLayer) { //If touching the 'Ground' layer.
     
  6. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    Right, there is much stuff that can be done, if you combine all 3 suggestions i guess you are fine :)
     
  7. AV_Corey

    AV_Corey

    Joined:
    Jan 7, 2016
    Posts:
    122
    I have just tried changing the code to:
    Code (CSharp):
    1. if (hit1.collider.gameObject.layer == groundLayer)
    and setting the LayerMask to the Ground layer in the Editor but it doesn't seem to work.

    I tried doing groundLayer.value too but that wouldn't work either.
     
  8. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    You should use the layer in the Raycast method. Then the ray will only be checked against colliders in that layer which is faster. As you don't do anything then you also need no RaycastHit object as you only check if you hit something in that layer.
    You can also use LayerMask instead of int, this is more convenient if you expose it in the Inspector somewhere.
    Code (CSharp):
    1. private bool MyRaycastMethod(Vector3 position, float distance, LayerMask layer)
    2. {
    3.     Debug.DrawRay(position, Vector2.down * distance, Color.green);
    4.  
    5.     var ray = new Ray(position, Vector2.down);
    6.     return Physics.Raycast(ray, distance, layer);
    7. }
     
    AV_Corey likes this.