Search Unity

How to declare enums with float value.

Discussion in 'Scripting' started by Rond, Jan 25, 2011.

  1. Rond

    Rond

    Joined:
    Oct 21, 2009
    Posts:
    175
    Hi,
    I'm trying to make and enum that contains informations about the rarity of a item and i'm using enums, but if make it this way, the console report a error..
    Code (csharp):
    1. enum itemRarity () {
    2.     veryCommon = 10,
    3.     common = 8.5,
    4.     semiRare = 6.75,
    5.     rare = 3.33,
    6.     veryRare = 1.25
    7. }
     
  2. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Sorry, can't be done. Enums are strictly integers/bytes. Really, they are supposed to be their own type. The backing field is just to help with special cases (serialization, bitwise operands, etc.). Although there are exceptions, for the most part, your code shouldn't care about their backing values and shouldn't be using them as such.

    There are some tricks to attach values to them via C# attributes (don't know if that's supported in JavaScript though) but that's pretty cumbersome too and requires reflection.

    Easiest solution for now is to create a method that can provide you that info:
    Code (csharp):
    1. enum itemRarity () {
    2.     veryCommon,
    3.     common,
    4.     semiRare,
    5.     rare,
    6.     veryRare
    7. }
    8.  
    9. public function GetItemRarityPercentage(itemRarity rarity) : float
    10. {
    11.     switch (rarity)
    12.     {
    13.         case itemRarity.veryCommon :
    14.             return 10;
    15.         case itemRarity.common :
    16.             return 8.5;
    17.         case itemRarity.semiRare :
    18.             return 6.75;
    19.         case itemRarity.rare :
    20.             return 3.33;
    21.         case itemRarity.veryRare :
    22.             return 1.25;
    23.     }
    24.    
    25.     //unhandled rarity?
    26.     return 0;
    27. }

    EDIT: the added benefit of doing it this way is you abstract the concept of a "rarity" from its percentage values. Consider if you were storing this information in your game (for saving/loading), you would save a concept of a "semiRare" item by storing the value "6.75". If later you alter your game mechanics so that number changes to say, "5.50" then all of sudden your game starts breaking down because it doesn't know what a "6.75" is anymore.
     
    Last edited: Jan 25, 2011
  3. pakfront

    pakfront

    Joined:
    Oct 6, 2010
    Posts:
    551
    Enums can only be ints, not floats in C# and presumably unityScript. Maybe you want a constant or a static readonly?
     
  4. Rond

    Rond

    Joined:
    Oct 21, 2009
    Posts:
    175
    No, not a constant, but is read only, so i think it can be made that way above. Thank you both... :D
     
  5. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    An example of pakfront's suggestion might be:

    Code (csharp):
    1.  
    2. public static class ItemRarity
    3. {
    4.     public const float VeryCommon = 10;
    5.     public const float Common = 8.5;
    6.     public const float SemiRare = 6.75;
    7.     public const float Rare = 3.33;
    8.     public const float VeryRare = 1.25;
    9. }
    The only problem with that, is that the rest of your code doesn't work against a typed "ItemRarity" object or enum and are just passing floats around. But maybe that's more than sufficient for you.

    Another typed option which allows for more properties to be attached to rarities (like colour) would be to define a custom class and lock the possible instances of it:
    Code (csharp):
    1.  
    2. public class ItemRarity
    3. {
    4.     public static readonly ItemRarity VeryCommon = new ItemRarity(10, "Grey");
    5.     public static readonly ItemRarity Common = new ItemRarity(8.5, "White");
    6.     public static readonly ItemRarity SemiRare = new ItemRarity(6.75, "Green");
    7.     public static readonly ItemRarity Rare = new ItemRarity(10, "Blue");
    8.     public static readonly ItemRarity VeryRare = new ItemRarity(10, "Purple");
    9.  
    10.     public float RarityPercentage;
    11.     public string Colour;
    12.    
    13.     private ItemRarity(float rarityPercentage, string colour)
    14.     {
    15.         this.RarityPercentage = rarityPercentage;
    16.         this.Colour = colour;
    17.     }
    18. }
    19.  

    I coded all these in C# because it's more natural for me, but it should give you the gist of it.
     
    MysleyMakers likes this.
  6. Rond

    Rond

    Joined:
    Oct 21, 2009
    Posts:
    175
    Well, i think the best way is creating a method to return the rarity value, thus, i can choose the item rarity by name in a list on the inspector... Thxx
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You could always just multiply by 100:

    Code (csharp):
    1. enum itemRarity () {
    2.     veryCommon = 1000,
    3.     common = 850,
    4.     semiRare = 675,
    5.     rare = 333,
    6.     veryRare = 125
    7. }
    However, I'd suggest you do what FizixMan said in his first post.

    --Eric
     
    Jeshira likes this.
  8. ByteJunk

    ByteJunk

    Joined:
    Apr 10, 2013
    Posts:
    4
    I'm very sorry for necro'ing this, but I really needed to raise my hat at Chris Sinclair. That's pretty much a drop-in replacement to a float enum, and just perfect for what I need. This is going into my "toolbelt".
    Kudos, sir!
     
    Westland likes this.
  9. joel_cambrian

    joel_cambrian

    Joined:
    Aug 30, 2017
    Posts:
    1
    I would also suggest using the power function if your numbers aren't needing to be as precise. It helps with a better distribution, and it's simpler. Like so:
    Code (csharp):
    1.  
    2. var strength = Math.Pow(2.0, myRarityEnumInt);
    3.  
    If your numbers have a linear relationship then just use a multiplier. You can play with the integers in the enum and the constant in the power function. This way, I'm able to keep my enums as whole numbers, aka 1,2,3,4,5, ... and just have the single line formula create the distribution. If you need a very specific distribution, you can just solve the algebra.
     
  10. Jeshira

    Jeshira

    Joined:
    Aug 3, 2017
    Posts:
    12
    I know I'm necroing, but it is something that turn up in Google when you search "float enum c#". Maybe you'd like a slightly over-engineered solution, but elegant in my opinion. Also compatible with Unity Inspector.

    Code (CSharp):
    1.  
    2. public class Item{
    3.   static readonly float[] rarityRate { 10.0f, 8.5f, 6.75f, 3.33f, 1.25f };
    4.   static readonly Color[] rarityColor {Color.grey, Color.green, Color.yellow, Color.red, Color.orange };
    5.  
    6.   public RarityClass RarityClass = RarityClass.VeryCommon;
    7.  
    8.   public float RarityRate { get { return rarityRate[RarityClass]; } }
    9.   public Color RarityColor { get { return rarityColor[RarityClass]; } }
    10. }
    11.  
    12. public enum RarityClass {
    13.     VeryCommon = 0,
    14.     Common,
    15.     Uncommon,
    16.     Rare,
    17.     VeryRare
    18. }
    19.  
    Alternatively using a struct,
    Code (CSharp):
    1.  
    2. public struct ItemRarity {
    3.     public readonly string Name;
    4.     public readonly Color Color;
    5.     public readonly float Rate;
    6.  
    7.     public ItemRarity(string name, Color color, float rate) {
    8.         Name = name;
    9.         Color = color;
    10.         Rate = rate;
    11.     }
    12. }
    13.  
    14. public class Item{
    15.   static readonly ItemRarity[] Rarities = {
    16.         new ItemRarity("Very Common", Color.grey, 10.0f),
    17.         new ItemRarity("Common", Color.green, 8.5f),
    18.         new ItemRarity("Uncommon", Color.blue, 6.75f),
    19.         new ItemRarity("Rare", Color.yellow, 3.33f),
    20.         new ItemRarity("Very Rare", Color.red, 1.25f),
    21.     };
    22.  
    23.     public RarityClass RarityClass = RarityClass.VeryCommon;
    24.     public ItemRarity Rarity { get {  return Rarities[RarityClass]} }
    25. }
    26.  
    27. public enum RarityClass {
    28.     VeryCommon = 0,
    29.     Common,
    30.     Uncommon,
    31.     Rare,
    32.     VeryRare
    33. }
    34.  
    Then you'll be able to do object.Rarity.Name, object.Rarity.Color, object.Rarity.Rate.
     
    Last edited: Dec 15, 2020
  11. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    I recently found myself here and was inspired by your structure, so here's a similar solution that uses indexers to improve ease of access to the data, as well as allows use with either a default dataset or entity specific data sets depending on need.

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3.  
    4. public static class Haptics {
    5.     public const float FREQUENCY = 50f;
    6.     public enum Pattern {
    7.         Short = 0,
    8.         Medium,
    9.         Long,
    10.         DotDot,
    11.         DotDotDot,
    12.         DashDash,
    13.         DashDashDash,
    14.         LineLine,
    15.         LineLineLine
    16.     }
    17.     public struct Timing {
    18.         public float duration { get; private set; }
    19.         public float pause { get; private set; }
    20.         public float pulses { get; private set; }
    21.  
    22.         public Timing(float duration, float pause = 0f, int pulses = 1) {
    23.             this.duration = duration;
    24.             this.pause = pause;
    25.             this.pulses = pulses;
    26.         }
    27.     }
    28.  
    29.     public class HapticTiming {
    30.         readonly Timing[] _arrTiming;
    31.  
    32.         public Timing this[Pattern indexer] {
    33.             get => _arrTiming[Math.Clamp((int)indexer, 0, _arrTiming.Length - 1)];
    34.         }
    35.  
    36.         public HapticTiming() {
    37.             List<Timing> lstTmp = new List<Timing> {
    38.                 new Timing(0.15f),
    39.                 new Timing(0.3f),
    40.                 new Timing(0.5f)
    41.             };
    42.  
    43.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Short].duration, lstTmp[(int)Pattern.Short].duration * 1.5f, 2));
    44.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Short].duration, lstTmp[(int)Pattern.Short].duration * 1.5f, 3));
    45.  
    46.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Medium].duration, lstTmp[(int)Pattern.Medium].duration * 1.5f, 2));
    47.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Medium].duration, lstTmp[(int)Pattern.Medium].duration * 1.5f, 3));
    48.  
    49.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Long].duration, lstTmp[(int)Pattern.Long].duration * 1.5f, 2));
    50.             lstTmp.Add(new Timing(lstTmp[(int)Pattern.Long].duration, lstTmp[(int)Pattern.Long].duration * 1.5f, 3));
    51.  
    52.             _arrTiming = lstTmp.ToArray();
    53.         }
    54.  
    55.         public HapticTiming(Timing[] timingData) {
    56.             if(timingData is null || timingData.Length < 1) {
    57.                 throw new ArgumentException("Array not populated, or has no values assigned!", "timingData");
    58.             }
    59.             _arrTiming = timingData;
    60.         }
    61.     }
    62. }
    63.  
    Use it as follows:
    Code (CSharp):
    1. public class MySystem{
    2.    //Instantiate timings
    3.    Haptics.HapticTiming _hapticTimings = new Haptics.HapticTiming();
    4.  
    5.    public void ReportHapticDuration(Haptics.Pattern pattern){
    6.        Debug.Log(_hapticTimings[pattern].duration);
    7.    }
    8. }
    9.  
    10. public class MyOtherSystem{
    11.    //Instantiate timings
    12.    Haptics.HapticTiming _hapticTimings = new Haptics.HapticTiming(new Timing[] { new Timing(0.15f), /*etc...*/};);
    13.  
    14.    public void ReportHapticDuration(Haptics.Pattern pattern){
    15.        Debug.Log(_hapticTimings[pattern].duration);
    16.    }
    17. }
    18.  
     
    Last edited: Sep 28, 2022
    Jeshira likes this.