Skip to main content
Elaborating
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

The last option with the array gives you more flexibility to work with two different nomenclatures, but you do introduce an extra point of failure where the array and the enum could get out of sync. (Saysay you reorder items, or insert/remove items in one place but not the other).

But the obvious downside is that now if you want to change your item IDs, you have to change them in three places: the enum, the array, and the test. So for that reason, I'd generally lean toward the options that use the enum names/values directly, without any secondary name storage anywhere that could go out of sync. Minimize surface area for potential bugs. 😉

The last option with the array gives you more flexibility to work with two different nomenclatures, but you do introduce an extra point of failure where the array and the enum could get out of sync. (Say you reorder items, or insert/remove items in one but not the other)

The last option with the array gives you more flexibility to work with two different nomenclatures, but you do introduce an extra point of failure where the array and the enum could get out of sync (say you reorder items, or insert/remove items in one place but not the other).

But the obvious downside is that now if you want to change your item IDs, you have to change them in three places: the enum, the array, and the test. So for that reason, I'd generally lean toward the options that use the enum names/values directly, without any secondary name storage anywhere that could go out of sync. Minimize surface area for potential bugs. 😉

deleted 11 characters in body
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

enter image description hereInspector Example

enter image description here

Inspector Example

Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

This looks like a job for an enumeration type!

public enum ItemId {
      TreeBarkUpgradeOne,
      TreeBarkUpgradeTwo,
      TreeBarkUpgradeThree,
      //...
      InflatablePalmTree
}

Now instead of a public int itemNumber, your ItemStats component has a public ItemId id.

enter image description here

Bonus: this gives you a drop-down in the Inspector that's a lot more legible than a bunch of magic numbers, and it still fits in the same int worth of storage and serializes/deserializes fine, because an enum value is still just a number under the hood.

You can then use these names directly as your player prefs IDs:

public static string GetPreferenceName(ItemId id) => id.ToString();

Or you can modify the name:

public static string GetPreferenceName(ItemId id) => $"{id}_Unlocked";

Or if you need names that are very different than the internal names of your enum members, and not in a consistent way you can boil down to a formula, you can store those in an array and look them up by exploiting the fact that an enum value is an integer:

static readonly string[] ITEM_PREFS_IDS = new string[] {
    "Tree Bark Lv 1",
    "Tree Bark Lv 2",
    //...
    "Inflatable Palm"
};

public static string GetPreferenceName(ItemId id) =>ITEM_PREFS_IDS[(int)id];

With any of these, your prefs string lookup is just a one-liner instead of a massive switch statement.

For the first two, you may not even need a test for this at all, since you're guaranteed that the names the designer sees in the inspector when configuring the item will always map 1:1 with the prefs names generated from them.

The last option with the array gives you more flexibility to work with two different nomenclatures, but you do introduce an extra point of failure where the array and the enum could get out of sync. (Say you reorder items, or insert/remove items in one but not the other)

For that, you're basically back to your switch statement to have a second, independent check. But you can write that more concisely with a little helper:

static void CheckPrefsIdMatch(ItemId id) {
    string expected = id switch
    {
        ItemId.TreeBarkUpgradeOne => "Tree Bark Lv 1",
        ItemId.TreeBarkUpgradeTwo => "Tree Bark Lv 2",
        //...
        ItemId.InflatablePalmTree => "Inflatable Palm",
        _ => "Unknown ID!"
    };
    string observed = GetPreferenceName(id);
    UnityEngine.Assertions.Assert.AreEqual(expected, observed, 
         $"Mismatched prefs id for Item Id {id}: expected {expected} but found {observed} instead."
    );
}

Then your tests can be simpler and less repetitive:

[UnityTest]
public IEnumerator UserGetsTreeBarkUpgrade()
{
    CheckPrefsIdMatch(ItemId.TreeBarkUpgradeOne);
    yield return null;
}