How to organise drop tables?

I have an Item class setup, which contains other classes that use it as a base eg. Consumable or Weapon.
I want to have a drop table script or asset or something, where I would have an array of pairs which are an Item and float as its drop chance.

I’ve got it working with a DropTable class as a Scriptable object, where I could make assets and then choose however many items I wanted to drop. However, I could not set the chances this way, as unity won’t allow me to serialise tuples which I tried switching to.

What I’ve got in mind is some base class DropTable, and then a new script for each table that derives from the DropTable base class. in each script somehow make these pairs of Item and float.

So my question is whether this is the way I should do it or if there’s a better way to implement this that I overlooked.

Using ScriptableObjects for the item is good here. But I think you want to structure it a little differently.

ScriptableObject → your BaseItem item as you noted.

DropTable → Another ScriptableObject that contains a list of “item and chance” classes (which are not ScriptableObjects, just regular serializable classes)

The ItemAndChance class would simply be something like:

[System.Serializable]
public class ItemAndChance
{
  public BaseItem Item;      // this refers to a scriptableobject
  public float Chance;
}

So that would suffice for your tuple.

The DropTable would have a list of ItemAndChance slots filled out.

This divorces the chance of a particular item dropping in any given table. If you are in a low-level dungeon, it would have a very low chance of dropping a high level item, but in a higher level dungeon with a different DropTable, there would be different loot with different chances.

If I understand you here correctly, ```
public BaseItem Item; // this refers to a scriptableobject

means that my item class should be a scriptable object?
I think It wouldn't actually be hard to implement that based on what I've got, I think I could just add SO as a base class for my Item class.

```csharp
using UnityEngine;

[System.Serializable]
public class Item
{
    public Sprite sprite;

    public class Consumable : Item
    {
        public Consumable(Sprite sprite)
        {
            this.sprite = sprite;
        }
    }

    public class Equipment : Item
    {
        public class Weapon : Equipment
        {
            public float damage;
            public Weapon(Sprite sprite, float damage)
            {
                this.sprite = sprite;
                this.damage = damage;
            }
        }

        public class Armour : Equipment
        {
            public Armour(Sprite sprite)
            {
                this.sprite = sprite;
            }
        }
    }
 
}

Then would I just be able to create assets of this SO?

Ok so I tried this, and wasn’t able to choose whether an item is a consumable or a weapon etc, but managed to solve it by putting [CreateAssetMenu] before the class declaration of Consumable or Weapon. Now I can just go to create > weapon etc.

Nevermind, I can’t seem to be able to find a way to reference an item now. What i had before is an Item class, extended with things such as consumable, and had an ItemDB class that stored those items. Now that the items are scriptable objects i cant seem to find a way to create a reference to them. I tried making a public array of type Item and ScriptableObject, but when I go to drag the .asset file in I get “Type cannot be found: Item+Consumable. Containing file and class name must match”

Nevermind again, managed to fix that by putting the Consumable class into another script, but I can’t understand why I would have to do that.

1 Like