Heymity / UniversalInventorySystem

A Unity Package for creating easy to use and highly customizable inventories and inventory`s UI
https://heymity.github.io/UniversalInventorySystemDocs/
Apache License 2.0
230 stars 21 forks source link

What is the purpose of the item registry? #21

Open Vyeche opened 8 months ago

Vyeche commented 8 months ago

I noticed that it has an abstract definition of items. Similar to the inventory interface.

What is the purpose of the registry(Scriptable Objects) vs inventory?

Heymity commented 8 months ago

There were some errors in the order in which I was implementing the system.

Basically the idea is for the system to be mostly not dependent on Unity, so it could easily be ported to MonoGame for example and easily usable in code, whithout needing do rely on the Editor.

Items implement the IItem interface. They are models for the item. Basically an ID for that item with its default data. An actual item is an ItemStack which implements the IItemStack interface. This is a 'created' item, it has a copy of the default data that can be modified, an amount, etc...

So basically items in inventory or in game are IItemStacks while the item you edit on the editor or create in code are IItem and serve as a model for the actual IItemStacks.

The IItemRegistry is where the IItem lives in. You can have any amount of registries and their purpose is to organize items both in editor and in code. An IItem could exist outside of registry, but if you are defining it in code you will need somewhere to 'save' it, so you would end up needing something like the IItemRegistry.

Now here is where it gets messy.

To be able to create and edit the items in the Editor I am using Scriptable Objects. So there is a class that is a SO and is a IItemRegistry to be used in the editor. The problem is that in the Editor you don´t have polymorphism support*, so if hava a WeaponItem : IItem and has a WeaponData : IItemData as its item data, you would need to create a new SO registry class that has a list of WeaponItem type, since the provided one is using the BasicItem class. So for each type of item you would need a new SO class. Thats why I created the AbstractItemDefinition. Being a SO, the ItemRegistry : SO would have a list of AbstractItemDefinition and this way classes that inherit from AbstractItemDefinition would be able to be assigned to the ItemRegistry : SO in the Editor.

(*) If the classes are ScriptableObjects you kind of have polymorphism in the Editor

I am not sure this is the best way as it creates a lot of confusing nomenclature and use, I have been thinking on better ways to approach this problem and is highly likely that this class (AbstractItemDefinition) will be removed in the future.

TL;DR

Its confusing, in the future this will probably change but its a workaround to be able to use diferent item types in the same ItemRegistry : SO

If you have any further questions please ask. This project is lacking documentation on a chronic level, this comment is the best documentation it has right now.

Vyeche commented 8 months ago

I see. Thank you for the detailed explanation!

My initial thought was it was a database allowing me to either add things to it via code or through the editor. I had even thought about using the registry to export the data to sql lite etc.

Vyeche commented 8 months ago

I'm curious why you didn't go with the Ryan Hibble approach to letting the designers mix and match pieces.

I remember watching the Unite 2017 talk with Ryan. Perhaps the four pillars he described in his talk could be another route. I'm quite happy with using Registry as a runtime set or a variable and even implementation of events when commands are issued. Although I don't know how good his system is in production to me it sounds exciting.

What are your thoughts on allowing the designers to build the inventory instead of developers.

@Heymity

Vyeche commented 8 months ago

Sidebar, I noticed that an ID isn't automatically generated per new item creation in the registry or the add inside the inventory. What is the plan for finding items in the inventory by ID (GUID)?

@Heymity

Heymity commented 8 months ago

So this project suffers from a very common problem in free/open source assets which is lack of time. The goal is for the registry to be editable via code, editor and any other means the client might wish. But that takes a lot of work. I started this project in 2020 when I had way more free time than today. The original system is quite complete, but it is very restricted when it comes to the technical aspects of it. The new version aims to solve this, but that means for it to be complete it will take some time.

Now as for the Unite 2017 talk you mentioned. I have watched it and think it's a great system. I hadn't really thought of implementing it in this project, but it seems to be a good idea that could solve some problems. The idea of the project is to be easy to use, but without restricting its possibilities, so allowing the designers to build the inventory is one of the goals, but like I said earlier, it takes time to make.

The original idea was for the item IDs to be user-defined, so that they could be more 'searchable' (since knowing the GUIDs for hundreds of items from the top of one's head is just madness) but that could also be changed to be a 'displayID' or something like that, but I think that would be weird (having two IDs per item). What can be made is if the ID is empty one that is a GUID is created to it automatically. Not 100% sure this is what you were asking so if any doubts remain please ask!

Vyeche commented 8 months ago

@Heymity In regards to the ID I see it as a SQL query. Sometimes in the code I need to find things by ID. (As an option)

Let's say a quest requires six sticky mucus and three dead branches. I much rather search it up by ID then string or what have you. Perhaps the designer could use the runtime set to establish a query without IDs using the observer pattern. Keeping in mind that the quest items could listen for specific inventory items.

Let me know if that removes some doubt?

Heymity commented 8 months ago

I am not sure I understand.

The thing is every ItemStack has a reference to an Item, which means you could access it without any search, and only if you don't have any reference to the Item you would need to search it. In that case the item ID exists, which is a user defined string to be easily rememberable. With this ID you can search any item. It could very well be an GUID but than you would have to remember the GUID (Just for clarity, with GUID I am refeering just to the 128 bit usual implementation and format, since the item IDs are unique an global as well). And if you set this GUID from somewhere else like an editor reference, you could just use the Item reference itself, avoiding the need for a search and a indirect reference.

I am not sure if I am missing something obvious here for why an GUID would be better than a user defined global unique string ID (that if empty would be set to a new GUID), if I am please point out!

(Also sorry for late response)

Vyeche commented 8 months ago

I am not sure I understand.

The thing is every ItemStack has a reference to an Item, which means you could access it without any search, and only if you don't have any reference to the Item you would need to search it. In that case the item ID exists, which is a user defined string to be easily rememberable. With this ID you can search any item. It could very well be an GUID but than you would have to remember the GUID (Just for clarity, with GUID I am refeering just to the 128 bit usual implementation and format, since the item IDs are unique an global as well). And if you set this GUID from somewhere else like an editor reference, you could just use the Item reference itself, avoiding the need for a search and a indirect reference.

I am not sure if I am missing something obvious here for why an GUID would be better than a user defined global unique string ID (that if empty would be set to a new GUID), if I am please point out!

(Also sorry for late response)

Perhaps I need to try it out and explore the system a bit more using ItemStack in the code. Since the inventory is a singleton I could find the ItemStack by the name.

From a database point of view, I’m thinking about a mapping table or lookup.

In the inventory I have the following items ItemName | ID sticky mucus | 14 Water bottle. | 3 Branch. | 6

Quest Requires QuestID | ItemID 3 | 14 3 | 3

I can find the required quest items by ID instead of name.