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. Dismiss Notice

Best practice for refactoring enum in ScriptableObject?

Discussion in 'Scripting' started by RaymingW, Oct 29, 2020.

  1. RaymingW

    RaymingW

    Joined:
    Nov 11, 2017
    Posts:
    36
    Hi all,
    I find refactoring enum when it is used in ScriptableObject can be very annoying. Say I have a piece of code like this.
    Code (CSharp):
    1. public enum NPCType
    2. {
    3.     Frog,
    4.     Dog,
    5.     Cat
    6. };
    7. public class NPC : ScriptableObject
    8. {
    9.     public NPCType npcTypes;
    10.     public float speed;
    11. }
    If I add another animal between Dog and Cat,
    Code (CSharp):
    1. public enum NPCType
    2. {
    3.     Frog,
    4.     Dog,
    5.     Mouse,
    6.     Cat
    7. };
    8.  
    All my pre-existed cat objects will turn into mouse. I know I can just append mouse after cat but I think there should be a better way to do this.

    Any advice?

    Cheers!
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    Enums are just serialized as a value iirc so you should be able to just specify those values. Try
    Code (CSharp):
    1. public enum NPCType
    2. {
    3.     Frog = 0,
    4.     Dog = 1,
    5.     Mouse = 3,
    6.     Cat = 2
    7. }
     
  3. RaymingW

    RaymingW

    Joined:
    Nov 11, 2017
    Posts:
    36
    Thanks! That worked!
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Normally, you want to use compiler features of enum types to full potential
    Code (csharp):
    1. public enum NPCType {
    2.   Frog = 0,
    3.   Dog,
    4.   Mouse,
    5.   Cat, // you can also keep this comma so that you can reorder them freely in the future
    6. }
    This is contrary to what you wanted, but in general, you want to make your enum handling code order-insensitive.
    If you depend on the exact values, this is not a smart choice, and you will likely run into trouble in the long run.

    The point of an enum value is usually not to represent critical information such as order, but to opaquely enumerate sequential constants and make arbitrary magic indices appear as text.

    If you really want to represent critical information, then do what WarmedxMints suggested, but when you really think about it, what's the point of doing it in this case? The difference is only an illusion, and you'll only fool yourself later.
    Code (csharp):
    1. public enum NPCType {
    2.     Frog = 0,
    3.     Dog = 1,
    4.     Mouse = 3,
    5.     Cat = 2
    6. }
    is the exact same thing as
    Code (csharp):
    1. public enum NPCType {
    2.     Frog = 0,
    3.     Dog,
    4.     Cat,
    5.     Mouse
    6. }
    The only difference (apart from the clutter) is that you've tricked your eyes into some false sense of order, which has no effect on your code whatsoever.

    The way you use enum values as 'critical' data is to correlate this ordering with some other mechanism, maybe some kind of priority etc. I.e. if you reorder data in this enum above
    Code (csharp):
    1. public enum NPCType {
    2.     Frog = 0, // this is only to make it more readable for your future self
    3.     Mouse,
    4.     Dog,
    5.     Cat
    6. }
    Your code shouldn't fall apart, but should instead treat Mouse as somehow more important than Cat IF the order should be relevant at all, and most likely it's just an ID, the exact value of which shouldn't matter during runtime, as long as 3 always maps to all things Cat, and 2 always maps to all things Dog etc.
    So what you're doing is a code smell.
     
    Last edited: Oct 29, 2020
    theforgot3n1 likes this.
  5. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    To put it short, the way you're consuming enum is not a good practice in itself, because you're defeating the purpose of an enum if you're tying up your code with the values themselves, instead of consuming only the names. This way you're working around the enum, and should probably use something else, like const or readonly values.
     
    theforgot3n1 likes this.
  6. Shiiv

    Shiiv

    Joined:
    Jul 29, 2020
    Posts:
    9
    I think using an enum this way makes sense when displayed with scriptable object.
    In my case i have an "Animation" enum : Attack1,Attack2,InstantCast1,InstantCast2, etc...
    Later in development i had to add "Attack3", i did not want it to appear at the end of the list obviously.
    So i decided to manually handle the value of each enum instead :
    Code (CSharp):
    1.     public enum Animation {
    2.         Attack1 = 0,
    3.         Attack2 = 1,
    4.         Attack3 = 4,
    5.         InstantCast1 = 2,
    6.         InstantCast2 = 3,
    7.     }
    8.  
    That way the enum is still displayed sorted as i want in the scriptable object, and i just have to be carefull when adding a new one, which is not supposed to happend a lot and seems like a very little drawback to me.
    Thanks for the insights anyway =)