Extendable Enums with ScriptableObjects

I think that anyone who got interested in the usage of scriptable objects has seen Richard Fine’s talk (link in case someone didn’t : Unite 2016 - Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution - YouTube).

It’s been really helpful and clear but the extendable enums things has not been explained with an example and i guess that it’s so easy that it doesn’t need one but for some reason i can’t wrap my head around it.

Suppose i have this enum: enum DmgType {Fire, Water, Air}

if i have a field with a type of DmgType i can do the following : dmgType.Fire.

What interests me a lot with enum is that when I’m writing that i get all the possible types in my enum and If i’m assigning its value in the inspector i get a dropdown with all the possible values.
So my question is how do you actually do that with scriptable objects

You just have to create a simple ScriptableObject as follow:

using UnityEngine;

[CreateAssetMenu( fileName = "DamageType", menuName = "DamageType" )]
public class DamageType : ScriptableObject{}

Then, in your other script, declare a serialized variable of DamageType type:

using UnityEngine;

public class Weapon : MonoBehaviour
    private DamageType damageType;

You will be able to drag & drop a DamageType asset into the serialized field of your Weapon class.

I know this post is 2 years old. But it is on top of the google search. So I try to give an answer to this. The problem with enum as a code construct is, that you have to check what kind of damage the weapon is doing before switch / case to the correct value of damage amount for example, or to which effect you play if the weapon hits. It would look like:

val damageAmount = 0;
case DmgType.Water:
    damageAmount = 2;
case DmgType.Fire:
    damageAmount = 4;
// ...

The same for all other decisions in code where you need to know what data you need for the current DmgType. Assume you could ask the enum itself for its damageAmount. Like this:

var damageAmount = damageType.amountOfDamage;

It is a one liner. The thing is you could put all these configuration values inside the ScriptableObject class you implemented for your enum type. For every other needed configuration do the same provide a property field in the ScriptableEnum class, that’s it.
Even conditional questions in code could be solved very easy.
For example if you have to decide if the weapon is usable on the enemy. For example there is a fire demon. And your weapon has the DmgType.Fire it is useless against this fire demon. Normally you make an if in the code. But think about the if then elses you need per enemy type to decide if the weapon is usable against them? With the scriptable enum it is easy just implement a:

    List<EnemyType> beatable;
   bool CanBeat(EnemyType enemytype)
        return beatable.Contains(enemyType);

into the ScriptableEnum class where you can easily put in all types of enemies that are beatable.
And the best thing is, if you have this kind of ScriptableEnums all over your code, it is absolutely easy to implement a new weapon without changing one line of code. Just create the new asset object and define all values, conditions and prefabs there. It will work all over your code automatically.
The funny thing is you will never have the need again to know if the weapon has the DmgType of fire. :slight_smile: