It really depends on the exact problem you are trying to solve, if all of the conditions are valid and independent, then that is exactly what if statements are for.
However, it is often the case that there are far more practical ways of dealing with multiple conditions, depending on the type of code. In some cases, state encapsulation or caching is more valid, sometimes, you can defer use of a condition to actually being integrated in the logic.
A Few Examples
- For situations where only a number of states can be true simultaneously, you can use a state machine instead (store state in a variable, using enums and then switch on it for logic).
- If you have a variety of independent systems which can all influence the output indirectly, I tend to prefer organising my code to avoid nesting, and tracking some validity:
GML:
var canDoSomething = true;
if(isDead){
canDoSomething = false;
}
if(isSunday){
canDoSomething = false;
}
if(specialOverridingPowerupMechanicThatAllowsMeToAvoidDeathTemporarily){
canDoSomething = true;
}
if(canDoSomething) {
justDoIt();
}
Vertical code can make your life easier, and also cater for greater control if you suddenly decide that you want one special condition that overrides the previous condition. The problem with nesting in this case is you would then need to add an OR condition to all of your otherwise valid statements.
- Similarly, as others have suggested, it can sometimes be preferable to store a bunch of these conditions in a variable, then just check the condition when other state updates:
Code:
var canDoSomething = (!isDead && !isSunday);
if(canDoSomething){
justDoIt();
}
- For situations where the logic is overly complex, you can also move the check into a different script, there's nothing inherently wrong with doing so in order to make your code neater. Combining the ideas of this, it can also be quite prudent to combine ideas, for example the ide of a state machine above, you can condense ideas down:
-
Code:
// function getState()enum MyStates { STATE_A, STATE_B, STATE_C};
if(!isDead && !isSunday){
if(someConditon){
return STATE_A;
} else {
return STATE_B;
}
} else {
return STATE_C;
}
// Use
var myState = getState();
switch(myState){
case STATE_A:
...
break;
case STATE_B:
...
break;
case STATE_C:
...
break;
}
- Finally, if you are using if statements to switch on item types for example, this should be entirely avoided if possible.
This is a picture from an open source game I once saw with their item switch implemented as a massive, horrendous, if-else chain:
In this instance, this is a perfect example of when NOT to use if statements.
For something like this, the logic for each individual item should be encapsulated in a separate script, and the script run.
Note that the reason if statements are used here, rather than a switch is that multiple items can be equipped at once, this chain captures all items. In reality, you could do this one after the other, but that would still incur a lot of waste as you are checking items that may not necessarily be equipped. -- I'd always suggestgiving each item its own script and allowing it to manipulate the logic.
Notes on Optimisation/Efficiency
Finally, wanted to make a comment on efficiency. Generally speaking, nested if statements will be no less efficient than separated vertical if statements. As a general rule of thumb, trust the compiler to do a better organisational job of structuring branching in your project than you do, it'll always find the best way based on the combination of logic used and whether it can collapse state. This is true for a lot of micro-optimisation.
Instead, your focus as a programming should be on two things:
- Readability and Maintainability (as we can see the code in the above statement is neither of these).
- Ensure what you are doing uses the best programming device for the task at hand, whether that be a data structure, a state machine, separate scripts, or nested if statements.