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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Using If Statements too much?

Discussion in 'Scripting' started by connorbaush, Mar 27, 2019.

  1. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    I'm very new to Unity(< 5 months). I'm equally new to C# (and coding in general).

    My script for the first prototype game I made, as well as the script for the game I'm currently working on are both largely made up of If Statements. Is it bad practice to rely heavily on them? Is there a common/more optimal alternative that I just haven't quite learned yet?
     
  2. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    It is bad practice, but it is also part of the learning process. Depending on the conditions your are checking for switch-case statements might be a better fit.
     
    Magiichan and Cyber-Dog like this.
  3. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    There is nothing wrong with using lots of if statements. Any non-trivial piece of software will contain many if statements.

    Perhaps you would like to share some code that you are not so sure about.
     
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,141
    Without seeing the script in question it's difficult to say. I have written code in the past that was on both sides of the fence when it came to the quantity of conditionals and it just worked with no problems.
     
  5. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    Writing software, too many IFs are not good. But when it comes to games they have a huge part to play. It all depends on how your using your IF statements. So don't worry if you use allot of them.

    As mentioned by @Laperen, switches can also be used. IFs/Switches/Whiles etc are all good ways to check when a condition is met. In some cases events may be the way to go. So you wouldn't have a Toggle UI button and have some code in Update checking if(Toggle.IsOn) you would make a function and fire the event on click.

    But the biggest thing you can learn, is the best way to use an IF statement efficiently, and clean.

    Code (CSharp):
    1. //I want to know when the player can jump, they must be grounded first.
    2. bool canJump = false;
    3. void Update()
    4. {
    5.     RaycastHit hit;
    6.     if (Racast(PARMSXYZ, hit))
    7.     {
    8.         if (hit = groud;)
    9.         {
    10.             if (ground close 2 player)
    11.             {
    12.                 canJump = true;
    13.             }
    14.         }
    15.        
    16.     }
    17.     if (press jump && canJump == true)
    18.     {
    19.         //Do Jump  
    20.     }
    21. }
    22.  
    23.  
    24.  
    25. //Do it like this
    26. bool canJump = false;
    27. void Update()
    28. {
    29.     if (press jump)
    30.     {
    31.         if (ground close 2 player)
    32.         {
    33.             if (Racast(PARMSXYZ, hit))
    34.             {
    35.                 if (hit = groud;)
    36.                 {
    37.                     //Do Jump
    38.                 }
    39.             }
    40.         }
    41.     }
    42. }

    In this example. The first piece of code is doing a physics check every frame. Even when the player is defiantly not going to be able to jump. So its wasted processing power.
    In the second one. It first checks if the player presses jump. if the player presses jump, then do a physics check which is more expensive than a button check. but not before doing a smaller check of is the player close to the ground.

    Now here is an example of were you would use a switch instead of If.
    Code (CSharp):
    1. //Do something depending on the day of the week
    2. string day;
    3. void Update()
    4. {
    5.     if (day == "Monday")
    6.     {
    7.         //Do something
    8.     }
    9.     else if (day == "Tuesday")
    10.     {
    11.         //Do something
    12.     }
    13.     else if (day == "Wednesday")
    14.     {
    15.         //Do something
    16.     }
    17.     //And so on....
    18. }
    19.  
    20.  
    21. //Btter like this
    22. string day;
    23. void Update()
    24. {
    25.     switch (day)
    26.     {
    27.         case "Monday":
    28.         //Do something
    29.         break;
    30.         case "Tuesday":
    31.         //Do something
    32.         break;
    33.         case "Wednesday":
    34.         //Do something
    35.         break;
    36.         //And so on....
    37.     }
    38.    
    39. }
    40.  
    And to iterate on the last one... You would never want to do something like this...
    Code (CSharp):
    1. //Do something depending on the day of the week
    2. string day;
    3. void Update()
    4. {
    5.     if (day == "Monday")
    6.     {
    7.         //Do something
    8.     }
    9.     if (day == "Tuesday")
    10.     {
    11.         //Do something
    12.     }
    13.     if (day == "Wednesday")
    14.     {
    15.         //Do something
    16.     }
    17.     //And so on....
    18. }
    19.  
    Because you know that the day can only be one thing, so dont check several times if you know it can only be one.
     
  6. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    I hope that helps mate :)
     
  7. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    Cool tip for switch statements: if you're in visual studio, type "switch" and press tab, then put your variable into the brackets, and press tab again. It'll fill out the entire switch statement with all the cases for you!
     
  8. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    Wow, these are all helpful and very reassuring. I have tried using while statements, but every time I do it I run into what I assume is an infinite loop, and it freezes Unity. Should while statements be avoided in Update?
     
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    If statements can also be combined in some cases.

    Code (csharp):
    1. if (coolInt == 7)
    2. {
    3.     if (coolBool == true)
    4.     {
    5.         if (coolPlayer != null)
    6.         {
    7.             doSomethingCoolWithPlayer(coolPlayer);
    8.         }
    9.     }
    10. }
    The above can be simplified as:
    Code (csharp):
    1. if ((coolInt == 7) && (coolBool == true) && (coolPlayer != null))
    2. {
    3.     doSomethingCoolWithPlayer(coolPlayer);
    4. }
    Well you need to write your while loops in a way which prevents the possibility of an infinite loop, and don't use while loops in Update to wait for something because you're blocking the main thread - so what you're waiting for is probably never going to happen. You can also favor other types of loops that are less prone to becoming infinite loops, such as iterating over a collection using foreach.
     
    Last edited: Mar 27, 2019
    connorbaush and SparrowGS like this.
  10. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Please give examples preferably with use-cases so we can tell you if and why it's bad and what other approaches you can take on it.

    there's nothing wrong with using a lot of is statements if you need to check if something is one or the other, there are other ways to handle stuff like that like switch statements that have been mentioned.


    again, example please.

    something like this is "good"(although it probably doesn't belong in Update and is better handled by a for loop):
    Code (CSharp):
    1. List<Vector3>points; //populated somehow
    2.  
    3. while(points.Cound > 0){
    4.  
    5. Debug.Log(points[0));
    6. Remove(points[0]); //remove the 0-th element each iteration, when list in empty "points.Count" is bigger than 0 so we exit the loop.
    7. }
     
    Joe-Censored likes this.
  11. brian1gramm1

    brian1gramm1

    Joined:
    Sep 15, 2017
    Posts:
    55
    Reply to "While" loops. Yes, they can be very dangerous in Unity, but if used correctly and cautiously, can greatly improve event checking.

    1. Always be sure you have a condition that WILL CHANGE at some point in time. Either by unity, by your code, or even the user pressing a button. eg. while(Input.GetKeyDown(KeyCode.Space) == false) {//do something}
    2. Add a fail safe to help you prevent long while loops eg. int count = 0; while(true){ count ++; if(count > 1000)break;}
    3. I love while loops in IEnumerators. I use it for user actions, dialogue triggers, and timers.
     
  12. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    They are dangerous regardless of unity or even the language, they are dangerous because of what they do.

    Yes, but if your while loop is on the main thread unity won't do anything until it's done, and the input you can give the loop is only the input that was for that frame, remember, the Input class updates once per visual frame(along side with Update), so if you have "while(Input.GetKeyDown(KeyCode.Space) == false)" and space was not pressed down between the current frame and the previous frame it will get you an infinite loop, if space was pressed in such a fashion it will skip the loop entirely (unless you use "do" but that's another story).

    if you talking about a coroutine like I've just gave an example for in another thread than yeah, you can do the same with a while loop and break.
    1. for(int i = 0; i < sentences.Length; i++){
    2. Debug.Log(participants [sentences.character].ToString() + ": " + sentences.text);
      [*]

      [*]while(Input.GetKeyDown(KeyCode.Space) == false){ //wait for player to press space before printing next sentence
      [*]yield return null;
      [*]}
      [*]

      [*]}
     
    Joe-Censored and connorbaush like this.
  13. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    I don't have any specific examples, as I have gotten rid of any attempts at while loops and used some form of if/else statements instead. But I'm pretty sure I've just been using while loops entirely incorrectly. Here's a rough example of something I might have tried.


    Code (CSharp):
    1. public bool isRunning;
    2.  
    3. void Update()
    4. {
    5. while (Input.GetKey(KeyCode.LeftShift))
    6. {
    7. isRunning = true;
    8. }
    9. }
    10.  
    I think I realize now why this is a problem though. As soon as I actually press the Shift key it freezes on that frame because the only way to end the loop is to stop pressing the Shift key, which doesn't happen before the frame ends. At least, that's my understanding of why this doesn't work. In plain English, I just wanted to make it so that while I'm pressing the shift key, isRunning is true. So instead of the above code I opted to do something along the lines of:

    Code (CSharp):
    1. if (Input.GetKey(KeyCode.LeftShift))
    2. {
    3. isRunning = true;
    4. }
    5. else
    6. {isRunning = false;
    7. }
    Does that make sense?
     
  14. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    Yes, I believe that's essentially exactly what my problem was.
     
  15. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    In cases like that, you can avoid if statements and make the code more readable:

    Code (csharp):
    1. isRunning = Input.GetKey(KeyCode.LeftShift);
    --Eric
     
  16. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    The status of the keyboard is updated each frame in Unity. Frames cannot be processed while in your while loop (Your own code needs to finish executing before Unity can do anything), and as such Input.GetKey will return true forever, regardless of the status of the shift key.
     
    connorbaush likes this.
  17. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    Oh wow, yeah that's much better, and very simple. Not sure if that'll necessarily work for all of my failed while loop attempts, but it's definitely a better alternative to some of my if/else statements. Thank you.
     
  18. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    Yeah that makes sense. Once I press Shift that loop goes on forever. I came to a vague version of this conclusion when I decided to stop trying to use while loops in Update.
     
  19. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    493
    So right now you're thinking procedurally- where the logic flows from the top of the script to the bottom, and that's a great place to start- In fact it's probably the best place to start.

    When you level up, you're going to start noticing that your code starts getting brittle- you start adding functionality and then it breaks something elsewhere in the script. Or maybe you'll find yourself repeating lots of code and then when something changes, you have to make changes in 8 places instead of just 1.

    Then you're ready to start looking at design patterns and strategies that get rid of a lot of those if statements. You'll get to go back to your code and refactor it to make it a lot better- which to tell you the truth, is what you'll spend 70% of your coding time doing. It's all good experience.
     
    Yavuz_Selim, Suddoha and SparrowGS like this.
  20. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    Also, as your new I would recommend doing a few of the official Unity tutorials. You will see good ways to use IF statements, when they use them. And you will get exposed to things you didn't know about. learning new ways of doing things.

    These are some great learning tutorials and I recommend them everybody wanting to learn, even if your experienced. There is always something new to learn!!! The beauty of coding :)

    https://unity3d.com/learn/tutorials
     
  21. Deadcow_

    Deadcow_

    Joined:
    Mar 13, 2014
    Posts:
    130
    It's not quite what you asked for but here is one tiny code style hint, it might really improve code readability in case of heavy conditioning usage. Apply when possible.

    Instead of this
    Code (CSharp):
    1. {
    2.   if (foo != null}
    3.   {
    4.     var x = foo.Bar();
    5.     if (x > 0)
    6.     {
    7.       ....
    8.     }
    9.   }
    10. }
    do this
    Code (CSharp):
    1. {
    2. if (foo == null) return;
    3. var x = foo.Bar();
    4. if (x <= 0) return;
    5.  
    6. .....
    7. }
     
  22. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    loops are usually meant to iterate through a list of items, NOT to check conditions. Knowing when to use what is more important in your case it would seem. You will still need if-statements, just that you will find alternatives to how you are doing things now that are more practical.

    If you've already made a prototype of a game, showing us some code for review is going to be alot better than us giving random scripting advice. It shows us your skill level, what you might be misunderstanding, and allows us to give more detailed advice allowing you to learn better aswell.
     
  23. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Something on rare occasion I do to avoid infinite loops and locking the editor is build in a fail safe to break the loop if it starts running away. After I have tested the code and verified it doesn't result in an infinite loop I may remove my fail safe, or I might just leave it in since it doesn't hurt much. Saves me from having to end process the editor and potentially losing a bit of work.

    You might consider doing something like this while you're still learning loops, or when you're not entirely sure how some calls you're making inside the loop work.


    Code (csharp):
    1. void Update()
    2. {
    3.     int failsafe = 0;
    4.     while(something)
    5.     {
    6.         //Do stuff I care about here, doesn't matter what
    7.         //I expect that "something" will eventually resolve to false to end the loop on its own
    8.  
    9.  
    10.         //fail safe code so I don't accidentally lock the editor if "something" never actually resolves to false
    11.         failsafe++;
    12.         if (failsafe > 100)
    13.         {
    14.             Debug.Log("Warning - Hit likely infinite loop in Update MyWhateverScript.cs, breaking");
    15.             break;
    16.         }
    17.     }
    18. }
     
    SparrowGS likes this.
  24. connorbaush

    connorbaush

    Joined:
    Mar 27, 2019
    Posts:
    7
    I definitely appreciate all of this advice very much. What I've taken away from this is that:

    1. Using lots of if/else statements is not necessarily a bad thing
    2. Switch statements are a good alternative when appropriate
    3. Simple statements like isRunning = Input.GetKey(KeyCode.LeftShift); are very effective
    4. Some if/else statements are better being combined using && / | |
    5. Loops shouldn't be used to check a condition

    My prototype game is already not really reflective of where my scripting skills are, so sharing some code from that wouldn't really be relevant or helpful. My current project would be a better example, but I've already gotten enough advice from this thread to make some significant amendments. I think I'll take some time to rewrite some of what I'm currently working on before I need any more explicit advice.

    Thanks a ton for the enthusiastic responses. It's good to know the community is so helpful.
     
    Cyber-Dog likes this.
  25. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    This is a good practice. Just remember to consider performance when bundling IF statements. For example in my earlier posts about doing player jump with button press, physics and distance checks.

    In that case you would not bundle the button press, distance, and physics check into one big && check. Why?
    Because although it may reduce your code lines and look neater, your still checking if three things are true at once. But you will never need to do that physics check if the button wasn't pressed. So by breaking it up you will save on performance and learn good practices.
     
  26. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Actually no. If checks with && short-circuit, where it will stop evaluating as soon as it hits something that's false. So if you have "if (A && B && C)", and A is false, it won't bother checking B or C.

    --Eric
     
    jaydnwlsn, Munchy2007, Ryiah and 3 others like this.
  27. MrMatthias

    MrMatthias

    Joined:
    Sep 18, 2012
    Posts:
    191
    I'd recommend that you read the books of Robert c. Martin commonly referred to as Uncle Bob:
    • Clean code
    • Clean Architecture
    • The clean coder (not related to soap services)
    Another often quoted book is The Pragmatic Programmer by Andrew Hunt and Dave Thomas
     
  28. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    Ahh ok, thanks for that! :)
     
  29. simonlvschal

    simonlvschal

    Joined:
    Nov 17, 2015
    Posts:
    266
    well ye. i would say using to many is problematic in the sense of readability. Switch statements exist for the purpose of making it far more readable. and its also faster i believe.
     
  30. ngerbens

    ngerbens

    Joined:
    Nov 20, 2017
    Posts:
    33
    This is so good to know. Saves so much ifs and elses. Thank you!