Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question An enum, from a class, is not getting its correct value

Discussion in 'Scripting' started by LeFuji, Feb 25, 2021.

  1. LeFuji

    LeFuji

    Joined:
    Oct 2, 2018
    Posts:
    18
    Hello all!

    I have a soldier class, which store every information the object needs at runtime:

    Code (CSharp):
    1. [System.Serializable]
    2. public class SoldierClass
    3. {
    4.    
    5.     // Identification
    6.     private string teamTag;  // Blue, Red
    7.     private int myID;          // Range 1~5+
    8.  
    9.     // Stats and characteristics
    10.     [Range(10.0f, 30.0f)]
    11.     public int agility = 10;
    12.     [Range(10.0f, 30.0f)]
    13.     public int dexterity;
    14.     [Range(10.0f, 30.0f)]
    15.     public int endurance = 10;
    16.     [Range(10.0f, 30.0f)]
    17.     public int perception = 10;
    18.  
    19.     private float myAim;        // myAim is a bonus: character already miss for up to 5 points. Dexterity reduces this difference by up to 3 points.
    20.     private int health;
    21.  
    22.     private Vector4 stats = new Vector4(10, 10, 10, 10);   // Agility, Dexterity, Endurance, Perception
    23.  
    24.     public EnumerationLists.Specialities enumSpecialization;
    25.     private string spec;
    26.  
    27.     // Gear
    28.     public EnumerationLists.PrimaryWeapons enumPrimary;
    29.     public WeaponClass primary;        //
    30.     public EnumerationLists.SecondaryWeapons enumSecondary;
    31.     private WeaponClass secondary;   //
    32.     public EnumerationLists.MeleeWeapons enumMelee;
    33.     private WeaponClass melee;        // Knife only at the moment
    34.     public EnumerationLists.InventoryGear enumInv1;
    35.     private InventoryClass inv1;      // View List on InventoryClass
    36.     public EnumerationLists.InventoryGear enumInv2;
    37.     private InventoryClass inv2;      // Same as above
    38.  
    39.     public EnumerationLists.HeadGear enumHead;
    40.     private string helmType;     // Helm_AX - A 1~3 / B 1~7 / C 1~7 / D 1~5 / E 1~5 / F 1~4 / G 1~4 / H 1~2 / I 1~2 / J 1~4 / K 1~4 / L 1~5
    41.     public EnumerationLists.VestGear enumVest;
    42.     private string vestType;
    43.     public EnumerationLists.LegGear enumLeg;
    44.     private string pantType;     // Legs_A, Legs_B, Legs_C
    45.     public EnumerationLists.BackpackGear enumBack;
    46.     private BackClass extraBackpack;// extra_light_backpack, extra_backpack, extra_camelback
    47.     public EnumerationLists.VestPocket enumPocket;
    48.     private PocketClass extraPocket;  // extra_equip_A, extra_equip_B, extra_equip_C
    49.  
    50.     public EnumerationLists.SpawnLane enumSpawn;
    51.     private string spawnPoint;
    52.    
    53.  
    54.     public SoldierClass(int ID)
    55.     {
    56.         myID = ID;
    57.  
    58.         stats = new Vector4(agility, dexterity, endurance, perception);
    59.  
    60.         myAim = stats.y / 10 * 0.25f;
    61.         health = (int)(10 + 2 * stats.z);
    62.  
    63.         spec = enumSpecialization.ToString();
    64.  
    65.         primary.codeName = enumPrimary.ToString();
    66.  
    67.         secondary.codeName = enumSecondary.ToString();
    68.         melee.codeName = enumMelee.ToString();
    69.         inv1.codeName = enumInv1.ToString();
    70.         inv2.codeName = enumInv2.ToString();
    71.  
    72.         // Fazer um switch aqui onde leva em conta os itens de inv para confecção da string do helm?
    73.  
    74.         helmType = enumHead.ToString();
    75.         vestType = enumVest.ToString();
    76.         pantType = enumLeg.ToString();
    77.         extraBackpack.codeName = enumBack.ToString();
    78.         extraPocket.codeName = enumPocket.ToString();
    79.  
    80.         spawnPoint = enumSpawn.ToString();
    81.  
    82.     }
    83. }
    After this, I got a bunch of gets and sets.

    Note that the Enumerations are listed all on a script called "EnumerationLists" and with its own options, as seen below:


    upload_2021-2-25_12-29-21.png

    On the game manager, I have a list for each team, to store individual values for soldiers, depending on team:

    Code (CSharp):
    1. public List<SoldierClass> blueSoldierList = new List<SoldierClass>();
    2.     public List<SoldierClass> redSoldierList = new List<SoldierClass>();
    After the game manager gets these values (In the future, these values will be received from the player, that is going to select each property on the UI), each team spawn get their own list, based on tag, and start instantiating the soldiers, which will each request it's own values from the list the spawn have, based on ID.

    Long story short:

    Game manager get values from inspector
    Event "OnStartValue" fires, warning TeamSpawners their list is ready
    TeamSpawners get their soldierclass List based on tag and Instantiate the number of soldiers the list has
    Event "OnInstantiatedSoldier" fires, warning soldiers to get their own values

    Thing is, the values from enumerators (enumPrimary, enumSecondary, etc) are all getting null returns, even if they have a value selected (As seen on the image, I have the Enum Spawn selected at "NN_Lane" and a log I've set when spawning indicates the sp variable (The enumSpawn value gotten from the constructor) is null.

    Am I missing something from the use of enumerators? I thought it was rather easy: Set the known values and use a ToString() to get the selection itself, not the int value it would represent.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    It's probably the inv1 inv2 variables not being set.

    Either way, the answer is always the same... ALWAYS. It is the single most common error ever.

    Don't waste your life spinning around and round on this error. Instead, learn how to fix it fast... it's EASY!!

    Some notes on how to fix a NullReferenceException error in Unity3D
    - also known as: Unassigned Reference Exception
    - also known as: Missing Reference Exception
    - also known as: Object reference not set to an instance of an object

    http://plbm.com/?p=221

    The basic steps outlined above are:
    - Identify what is null
    - Identify why it is null
    - Fix that.

    Expect to see this error a LOT. It's easily the most common thing to do when working. Learn how to fix it rapidly. It's easy. See the above link for more tips.

    This is the kind of mindset and thinking process you need to bring to this problem:

    https://forum.unity.com/threads/why-do-my-music-ignore-the-sliders.993849/#post-6453695

    Step by step, break it down, find the problem.

    ALSO: some cautions on enums:

    Lines 28, 30, 32, etc. all are the actual enumeration. This means Unity only stores the integer associated with it. Yes, you may feel free to put your face into your palm now.

    This means if you have an enum with

    Code (csharp):
    1. foo,
    2. bar,
    3. bat,
    Those will serialize as 0, 1, 2 respectively in the Unity scene or prefab or scriptable object.

    If you decide to insert a new enum:

    Code (csharp):
    1. rookie,
    2. foo,
    3. bar,
    4. bat,
    Now every place that you USED to have foo, which came out as 0, will now be rookie, and on down.

    HUGE landmine just waiting to blow your entire leg off... completely silently. No warning, no nothing.

    If you serialize enums, NEVER reorder, delete or insert anything. Only add to the end of them.

    Or assign hard numbers to each rather than autoincrementing. That way you actually can reorder them however you like.
     
  3. LeFuji

    LeFuji

    Joined:
    Oct 2, 2018
    Posts:
    18
    Hey man! Sorry for taking too long to respond that...

    Yeah, I knew exactly when my object wasn't being initialized, it was when I was instantiating a new object, using the constructor. I used a lot of Debug.Log to get to a point where it was clear the enum.ToString() was passing null values, even tough I selected some of the options on the inspector.

    Thing is, this was mainly to avoid writing errors (Specially uppercase stuff since c# is case sensitive) during gameplay balances, and was not actually needed to continue my development process, and after being warned about reordering enums, which I will absolutely need, I just going to a written the gear name. Everything is working fine now.

    Thanks for the heads up man, the enum thing was a short fused bomb in my project.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Agreed. But your concern about mistyping things is 100% legit still.

    When I use enums that will be serialized, I always just use their .ToString() value and store it as a string.

    If I am not using enums, then I create a static class full of const strings and use those variables so the naming is consistent. This of course does not help me typing in fields in the editor. :)