- Home /
Item Registry System
I am trying to make an item registry system so I can access Item Prefabs and spawn them really easy but I've run into a couple roadblocks.
With this system, I am trying not to have to rely on Resources.Load() unless absolutely necessary. Thus I am currently trying to implement it with an empty object on screen that acts as a singleton that stores all Item Prefabs so I don't have to do anything.
However, there are two roadblocks I have run into. Firstly, if I use a dictionary to store items so I can key them by their item IDs, I can't just drag in prefixes really easily and will be forced to use Resources.Load(). Secondly, if I use an array to store items, keying them by ItemID gets A LOT harder.
Is there another method to do this without having to rely on Resources.Load()? Or is there a much simpler way other people are doing it and I am just overthinking things?
You could use an ScriptableObject class that represents an Item resource, having an ID and a reference to a prefab. Then you create an Item asset for each of your Items, and add to the array the assets. Finally, internally you use a Dictionary with key bing the ID defined by the asset, and the value the prefab.
Does this make sense?
totally correct. Serialized containers without the actual need of being in a scene should always be SerializedObjects.
$$anonymous$$y Items are already Scriptable Objects, but apparently I never thought of storing a prefab with them!
Answer by madks13 · Jul 26, 2018 at 02:27 PM
You do know you can make your own enumerable/dictionary? You just have to implement the corresponding interfaces. You can change the behaviour so that it takes a GameObject and sets the key automatically. You should define your own comparer methods though, since it will be hard comparing prefabs quickly with default comparers.
Edit : @DaUr3 i just want to add this small thing : as mentionned in the comments, using ints as keys is the most efficient way of looking up items by key. That said, Unity seems to return InstanceID when GetHash is called, and it's an int. So you might want to use those as keys.
Answer by ericford · Jul 26, 2018 at 02:56 PM
Rather than using a dictionary, you can use an array of structs to create a fake dictionary that you can modify in the inspector. I quickly wrote up some code that I think achieves what you are looking for:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public struct ItemInfo
{
public string itemID;
public GameObject itemPrefab;
}
public class TestDict : MonoBehaviour
{
[SerializeField] private ItemInfo[] items = new ItemInfo[0];
// Loops through the array of items, looking for a matching ID
public GameObject GetItem(string id)
{
foreach (ItemInfo item in items)
{
// If matching ID found, return that item's prefab
if (item.itemID == id)
return item.itemPrefab;
}
// No matching ID, returning null
return null;
}
}
The reason i suggested a dictionnary is because you can change the behaviour so it accepts prefabs and gets their id directly by itself. Also, string comparison is way slower so the performance takes a huge hit (magnitude order of 1000 with only 1000 items). Also, dictionnaries are optimised for item search by key, contrary to arrays. OP said it's a system, so it might be used for large quantites of items.
I completely agree, but I wanted to mention a nice trick: if the item IDs are ints, you can use them as keys into an array (or List), and there is no faster "dictionary" than an array with int keys. Of course, then the IDs should be small, non-negative numbers, and any discontinuity in the range of IDs is a waste of memory (although small, just the size of a "pointer").
So this is another reason why not to use string keys.
Would using an enum as the key be a smart idea? I'm just thinking usability-wise. If he needs to access this "dictionary" from multiple places in the game, he's going to need to keep referring back to the array/list to see what int is associated to each prefab. If he uses an enum ins$$anonymous$$d as the key, it would save him a lot of time and prevent mistakes.
Your answer