Search Unity

Inventory System

Discussion in 'Entity Component System' started by Spy-Shifty, Aug 7, 2018.

  1. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Hi guys,

    this is more a discussion about best practice in ECS!

    What's your architecture for an inventory system?

    My approach (hybrid):

    I distinguish between 3 kind of Entity Items:
    InventoryItemEntity:
    • ItemOwner : ISharedComponentData { public Enity owner }
    • Item : ISharedComponentData { public ItemDiscriptor discriptor; }
    • Stackable : IComponentData { public int amount; }

    GameObjectItemEntity:
    • Item: ISharedComponentData { public ItemDiscriptor discriptor; }
    • Position : IComponentData { public float3 value; }
    • Interactable : IComponentData { }
    • GameObject
    UIItem (Unity UI element with databinding...)


    I've 2 Systems that act on those types (and more for specific item effect usages)

    InteractionSystem:
    This system checks if the player can interact e.g. with the GameObjectItemEntity. If so it will create an InteractionEntityEvent
    • Interaction : IComponentData { public Entity user; public Entity interactsOn; }
    • PickupAction : IComponentData { }
    The InventorySystem will than act on the InteractionEntityEvent. It will first check if Interaction.interactsOn has a Item component. If so it will destroy the GameObjectItemEntity. Also it will filterer the InventoryItemEntities for the ItemOwner and the ItemDescriptor based on the GameObjectItemEntity data. If an Entitiy exists, it will increase the Stackable.amount; Otherwise it will create a new InventoryItemEntity.

    The InteractionSystem will also provide InteractionEntityEvent to create commands for InventoryItemEntity to drop or use items.

    What do you think? Is this approach good or bad?
    Whats your way to handle Inventory or similar stuff?
     
    Last edited: Aug 9, 2018
    AA-Matt likes this.
  2. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    From a simplicity of code perspective, I think it's pretty good using ItemDescriptor SharedComponent as a hashmap lookup.
    From a contiguous data perspective though, won't you end up with ItemOwner * ItemDescriptor chunks?
    Every InventoryItem will essentially be a seperate object taking up 16k of memory.
    You could perhaps make ItemDescriptor just an id IComponentData and use it as a lookup into a System based hashmap or array and even ItemOwner could be directly referenced by Entity instead of Shared, but that may not be worth the extra effort considering an inventory is probably not much of a performance or memory issue anyway.
    Also if we end up with the ability to set chunk sizes down the track, solutions like this for non-performance critical things won't be so bad anyway.

    I remember looking up about inventories in ECS design a while back and saw someone using a very heavy archetype design so it was all contiguous but I can't find it on these forums.
    I found this response from Unity Mike from one of my posts before I knew how SharedComponents worked.
     
    Spy-Shifty and AA-Matt like this.
  3. madks13

    madks13

    Joined:
    May 8, 2016
    Posts:
    173
    Umm, i stumbled upon this post since then i was wondering : since ECS is data oriented, wouldn't a relational tables data base approach (ie. SQL) be appropriate for an inventory system?

    For example :
    - Item data (id, description code, max stack, appearance id, icon id...)
    - Inventory data (id, owner id, size...)
    - Item-Inventory data (id, item id, inventory id, order, amount...)
    - Item-Inventory group data (inventory id, item-inventory list)

    You keep the group data as shared, that way you can iterate only on inventory ids, and quiclky find the items per inventory, then use the ids to get the data on either the inventory or item. The item-inventory data is for looking up wide.

    The inventory data is for separating it from the owner, which can have multiple inventories, think WoW, with multiple bags and bag sizes.
     
    Deleted User and Spy-Shifty like this.
  4. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Well the thing is I use an ScriptableObject (ItemDiscriptor) to store the sprite for gui, the prefab object and other item infos in it. I want to keep those information inside the entity. So that I can quickly edit the items props in the editor at runtime.

    Maybe there is a more elegant way to use ScriptableObjects in compination with the ECS.
     
  5. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Inventory normally originates from a server in most games. And it's not something you are doing constant queries on. So the simplest approach is keep the client structure the same as the server. Changes always originate from the server, just get applied to the client. The client doesn't have any real logic for items.

    Base items I just keep in scriptable objects, those are basically static data. So my actual inventory is an id plus attributes that can be custom per item. Everything else is a static data lookup.

    Assuming your inventory is managed by the server, then you really do not want different data structures on both ends. That will only lead to bugs, duplicate items, all sorts of bad things.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,770
    I use DB for storing items, objects properties and lua scripts. Strictly using SQLite atm. But if in the future I would need go for server, it wouldn't be hard for me, to transit data, or link to it.

    Unless you want something not to be modified, you don't expect add much often new features, specially after game release, sure go for hard coding into game.

    But as proposed, Storing externally of the game your data, is good thing. Make game data oriented and data driven. Easy to maintain. Also, this way you open route, for modding, if ever need in future. The last one is my one of the targets.
     
  7. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Well, I don't need a Database. The Inventory is just match based. How do you provide the information from a scriptable object to the ecs?

    Based on Singleton via Resource folder or is it assigned to the item object directly or do you have a ManagerObject or something like this?
     
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,770
    I never used Scriptable Object. But I suspect, you would need to go via Hybrid ECS approach.