Is there a way to use variables instead of constants in Switch statements?

Hey all. I’m working on a simple FPS and wanted to implement weapon switching by comparing a variable (currentWeaponID) to various other establish weapon IDs. So if I set currentWeaponID to 1, it will set the weapon sprite and logic to an Assault Rifle, if I set it to 2 it will set it to a Shotgun, etc…

I have two options: either use a simple switch statements or to use a bunch of if statements. I don’t really have an issue with using if statements, but a switch is cleaner and easier IMO for the amount of weapons that a game might have, and I want to introduce this type of logic to other game elements as well.

I get the following error code:

Assets\Scripts\GunLogic.cs(129,18): error CS0150: A constant value is expected

Doing some research I found that only constant values are able to be used. I was wondering if there was any way to bypass this or not. If not, no worries, but it would be helpful. I could hardcode the ID values, but if I want to add or remove weapons or change the order, that might become tedious as the project grows.

Appreciate any help, here is my code below:

void WeaponSwitch()
    {

        switch (currentWeaponID)
        {
            case weaponHandsID:
                Debug.Log(weaponHandsName);
                break;
            case weaponAssaultRifleID:
                Debug.Log(weaponAssaultRifleName);
                break;
            case weaponShotgunID:
                Debug.Log(weaponShotgunName);
                break;
            case weaponPistolID:
                Debug.Log(weaponPistolName);
                break;
            default:
                Debug.Log("ERROR");
                break;
        }
}

No, I do not believe this is possible.
I would instead recommend using something like ScriptableObjects or interfaces to make your weapons instead. As a rule of thumb for good coding, you should not have to modify a class in order to create a new one or add new content. I would make a system where you can create a new weapon script or object using a scriptable object or interface, and then write generalized code to work with all of them. As you said, it is very hard to scale when every item is hard coded into a system. I would recommend reading Unity’s ebook about the SOLID principles of OOP. It will help you a lot in this situation.

You can use relational patterns or constant patterns that includes literals. You could use if statements but I would suggest that you dont need either and that your code is more likely just poorly written as the logic in the cases seems to be identical or could almost certainly be general.


i.e. you are probably hitting this problem because of other problems in the way you are writing your code and if the method above is any indication, that does appear to be the problem.

You can use a loop and a list instead of a switch statement, then you can make it dynamic state machine and add in and remove as many elements as you want, even while it’s running. I do that for the state machine in my fuzzy pattern matching system I use for a couple of assets. I outlined it all in this article:

You can use scriptable objects for your weapon IDs.

List<WeaponID> weaponIDs;
WeaponID currentWeaponID;

Update(){
    foreach(WeaponID wID in weaponIDs){
        if(currentWeaponID==wID){
             Debug.Log(wID.name);
        }
    }
}

but if you are only going by currentWeaponID then you probably don’t need a loop at all, something more simple like:

    Update(){
        Debug.Log(currentWeaponID.name);
    }

all your info and stats for your weapons should be contained in one class, a scriptable object is great for a data container because you can share them among scripts in the editor.

Hi. You can use the LINQ syntax, as well as the new switch statement syntax, to use variable names instead of constants. It still functions identically to a switch statement (but I’m guessing, slightly less optimized).


void WeaponSwitch()
{
    var message = currentWeaponID switch
    {
        var value when value == weaponHandsID => weaponHandsName,
        var value when value == weaponAssaultRifleID => weaponAssaultRifleName,
        var value when value == weaponShotgunID => weaponShotgunName,
        var value when value == weaponPistolID => weaponPistolName,
        _ => "ERROR"
    };

    Debug.Log(message);
}

One important thing to note is that a lot of users are recommending dictionaries, since they have O(1) lookup time (instead of the O(n) of a switch-statement), as well as being more scalable. This is true, if you intend to have more than at least 20 weapon types. Past then, I would recommend re-designing your system. However, under like 10 types, a switch statement pretty much always out-performs a dictionary. I’ve tested this in my own personal projects.


In summary, if scalability and readability are important to you, go with dictionaries, or try a new design. If speed is the most important factor, the switch is the way to go. @Sohodollie