Multiple switches vs if-else conditions

Started by
10 comments, last by Drenith Wraithis 11 years, 10 months ago
I'm wondering what's more efficient, using inner switches, or lengthy if-else conditions, if you have 20+ cases which have multiple options for each case?

So I prototyped a menu system for npcs, and I'm trying to figure out if I could do it better. Basically there are potentially more than 20 npcs with dialogue over several levels in the game.

Currently, when you trigger a dialogue from an npc, it calls a function makeMenu(true, npcName, interactionNum){}


Within that function is a switch for the npcName, within the npc's "case:" it has an if-else to check interactionNum and I'm wondering if a second switch would be better, within a switch?


switch(npcName){
case "smith":
if(interactionNum == 0){}
if(interactionNum == 1){}
if(interactionNum == 2){}
if(interactionNum == 3){}
break;
case "mage":
if(interactionNum == 0){}
if(interactionNum == 1){}
if(interactionNum == 2){}
if(interactionNum == 3){}
break;
//etc repeated 20x
}


Instead of:

switch(npcName){
case "smith:
switch(interactionNum){
case 1:
//dialogue 1
break;
case 2:
//dialogue 2
break;
case 3:
.//dialogue 3
break;
}
case "mage":
switch(interactionNum){
case 1:
//dialogue 1
break;
case 2:
//dialogue 2
break;
case 3:
.//dialogue 3
break;
}
//etc repeated 20x
}



On top of this there are quests in addition to dialogue, and it's on mobile.

Any advice or recommended reading? Thanks
Advertisement
Don't use ifs or switches for that.
Create some kind of a dialog manager class which gets a game context as input and returns the appropriate dialog.
Store the dialog mapping in some external format so you can add, modify and delete without compiling.
Whenever I see a big switch or if-else block I think of the Strategy Pattern

Don't use ifs or switches for that.
Create some kind of a dialog manager class which gets a game context as input and returns the appropriate dialog.
Store the dialog mapping in some external format so you can add, modify and delete without compiling.

This is probably a better specific solution.

In general, if/else and switch performance varies by language. Generally switches are more readable for cases like this though, and rarely perform any worse than if/else. AVOID STRINGS AS SWITCH KEYS though. Much better to make some sort of enumeration/other uid that can go into the switch somehow. If/else comparisons too for that matter. String comparison can be redonkulously expensive and dangerous.
Thanks guys. I'm using C#, and can definitely switch out the strings for an int and just keep track of which npc is which number, or an enum/list of npcs.

I thought about using xml to hold the dialogue but it seems in the switch it wasn't terribly difficult to read/edit.

Currently each npc has a collider, when the player walks close enough and collides with the trigger, it toggles the menu elements and populates them with the text from the switch. I have a GUI layout of buttons/background/text placeholders which are toggled off in a Start() function, then when the player triggers a menu it enables the proper elements and updates their content. Then if the player touches "read more" button, it increments a pageNum variable, and re-calls the same function passing itself as the argument, and the incremented pageNum gets caught in an if() conditional and overwrites the text with the next page of dialogue and enable/disables any other buttons/icons available.

This is what the prototype looks like:

[media]http://www.youtube.com/watch?feature=player_detailpage&list=UUuPUwB98LX-ir9PKx1aN6Mw&v=oHyxnz24was[/media]

Thanks guys. I'm using C#, and can definitely switch out the strings for an int and just keep track of which npc is which number, or an enum/list of npcs.

I thought about using xml to hold the dialogue but it seems in the switch it wasn't terribly difficult to read/edit.

Currently each npc has a collider, when the player walks close enough and collides with the trigger, it toggles the menu elements and populates them with the text from the switch.


Again, the strategy pattern strongly applies here.

Have an interface such as:

IHasCollisionMenu
{
int CollisionMenuGetCount();
string CollisionMenuGetItemText(int item);
void CollisionMenuDoCommand(int index);
}

If you decide to add submenus and visual trees, just add another entry such as string GetCollisionMenuPath(). Allow your menu system to merge items with a duplicate path. The menu path to a command is just extra visual spice; you really just have a list of things to choose from regardless of if you chose to view it as a single list or as a fancy tree.


When you collide with a thing you can display whatever menu it has and let the object worry about the command details.

Don't spend time looking for micro-optimizations between if trees or switch statements in code that doesn't matter. Instead look at saving yourself hours or days of work by keeping a flexible abstract interface.
Indeed, in this case code speed is entirely minimal compared to ease-of-editing. This is not code which is called every frame, only when certain events happen. You don't want to recompile every time you change some dialog.
I agree with everyone else in the thread. Unless you are working on really high-performance code (say, a method that's executed several million/billion times per second, or a real-time scientific computation kernel), micro-optimizations which degrade code readability and maintenance are not called for (and unless you are fairly experienced with "the inner workings", the compiler will generally do a better job than you at making code run faster anyhow).

If it's just for academic interest or just pure curiosity, the short answer is: it depends on the language. In many languages a switch case is implemented as... a succession of if/else conditions, so there will be no difference. In others, a switch may be faster, or it may be much slower. The best way to tell is to time a practical example, changing the number of conditions and seeing how that affects the timings. If you're feeling adventurous you can even make a case study (no pun intended) out of it, with graphs and stuff, using various languages.

Optimizing the hell out of a bunch of conditions with hardcore assembler and insane bit hacks was useful back when computers took milliseconds to do a single calculation, where you could actually save several hours of computation with just a few tricks. Considering nowadays, a computer can add two numbers faster than an atom can decay, the gain is so minimal it is not even worth looking into. It simply doesn't make a difference unless the time saved constitutes a significant fraction of the program's actual running time.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Thanks guys. I'm still trying to digest the strategy pattern within my menu system, but it looks like something I need to overcome and understand as I use A LOT of switches in my game. Not all as long as my npc menu system, but whenever I want to choose one of several scenarios....

Example is my combat system. The player has 5 sword swings, when they press the attack button, it Random.Range(minSwing, maxSwing) and passes that into a switch which performs the attack for the number generated, each attack has a different damage amount and animation. As the player unlocks new attacks, the minSwing and maxSwing are incremented, with a total of 15 attacks but you start on 0-4, and at the end of learning them all you have access to swings 10-14 which do a lot more damage than 0-4. It's basically the same as rolling a 5 sided die and performing the action for whichever number you land on.

Another case is my magic system....14 different spells accessed from putting together a combination of 4 runestones and pressing attack. 1, 2, 3, 4 individually, or 1+2, 1+3, 1+4, 2+3, 2+4, 3+4, 1+2+3, 1+3+4, etc etc etc 14 potential combinations.

I'm working within Unity, so I'm trying to wrap my head around patterns in general within Unity. When I was making a html5 javascript sprite engine I bought a book "Javascript patterns" which was perfect for that project, now I'm trying to wrap my head around classes instead of the object/prototypal inheritance. I'm halfway through an O'Reilly book called "Learning C# 3.0" which helps making the switch from arrays to lists and enums, as well as utilizing get{} and set{}.

I'm a student learning with the hopes of making something I can put on the app store. My school uses Java but I like C#. Even my crappy C# runs faster than the best OOP javascript I ever encountered with html5.

My main goal is to complete a project I can use to get an entry level job or internship to get my foot in the door and gain experience. So my lengthy switches might scare people away. Ugh.

edit::I see there are tons of "strategy pattern" examples but it seems you still have to make 20 strategies and a way for it to determine which one to choose. Is it really shorter than the switch system I have?

I'm working within Unity, so I'm trying to wrap my head around patterns in general within Unity. When I was making a html5 javascript sprite engine I bought a book "Javascript patterns" which was perfect for that project, now I'm trying to wrap my head around classes instead of the object/prototypal inheritance.
...
My main goal is to complete a project I can use to get an entry level job or internship to get my foot in the door and gain experience. So my lengthy switches might scare people away. Ugh.

Unity3D relies heavily on composition with this pattern so I'm surprised you continue with your massive switch statements.

You frequently see code of the form FindObjectsOfType(IHasSomeFeature). You won't care if the object is a gun or a sword or a player or a door or a couch. If the object implements the interface then you get it in your list of results, and you can use the feature with it. That is what makes the pattern so powerful.



As for trying to get an entry level job, don't worry about that too much. Apply to jobs, use your game as a portfolio item no matter what state it is in; employers know that entry level workers need training before they become reasonably competent programmers.

This topic is closed to new replies.

Advertisement