{"id":14960821,"url":"https://github.com/ashblue/unity-elastic-inventory","last_synced_at":"2025-10-24T19:30:27.187Z","repository":{"id":179040189,"uuid":"642085369","full_name":"ashblue/unity-elastic-inventory","owner":"ashblue","description":"An easy to use Unity inventory framework built with scaling and extendability in mind","archived":false,"fork":false,"pushed_at":"2023-07-06T04:14:03.000Z","size":2123,"stargazers_count":36,"open_issues_count":4,"forks_count":1,"subscribers_count":5,"default_branch":"develop","last_synced_at":"2024-04-14T13:10:30.986Z","etag":null,"topics":["equipment","extendable","inventory","unity-package-manager","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ashblue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-05-17T19:38:56.000Z","updated_at":"2024-04-02T06:14:31.000Z","dependencies_parsed_at":"2023-07-07T11:46:16.227Z","dependency_job_id":null,"html_url":"https://github.com/ashblue/unity-elastic-inventory","commit_stats":{"total_commits":11,"total_committers":4,"mean_commits":2.75,"dds":"0.36363636363636365","last_synced_commit":"9224ce33baac6838b8a4bfb3b72d81f815b85dcb"},"previous_names":["ashblue/unity-elastic-inventory"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashblue%2Funity-elastic-inventory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashblue%2Funity-elastic-inventory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashblue%2Funity-elastic-inventory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashblue%2Funity-elastic-inventory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ashblue","download_url":"https://codeload.github.com/ashblue/unity-elastic-inventory/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219868698,"owners_count":16555686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["equipment","extendable","inventory","unity-package-manager","unity3d"],"created_at":"2024-09-24T13:23:05.136Z","updated_at":"2025-10-24T19:30:27.167Z","avatar_url":"https://github.com/ashblue.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unity3d Inventory Framework - Elastic Inventory\n\nAn extendable Unity3D inventory library that leaves the implementation up to you. From simple inventory management to complex systems seen in Dark Souls, Diablo, Skyrim, ect. Stop rewriting your inventory and start building your game.\n\n![Unity3d Inventory](images/preview.png)\n\n**Features**\n\n* Instantly usable. Run the setup wizard, add an InventoryHelper, and you're done\n* Built-in save/load support for customizable item properties (damage, durability, ect)\n* Visual editor for managing item definitions\n* Real-time inventory debugging\n* Extendable item definitions (create weapons, tools, recipes, ect)\n* Support for unique and stackable items\n* Battle tested with automated tests\n* Built for Unity (no integration overhead)\n\n**Support**\n\nJoin the [Discord Community](https://discord.gg/8QHFfzn) if you have questions or need help.\n\n## Sample Usage\n\nHere is a practical `PlayerInventory` built with Elastic Inventory. You can shop, equip weapons, and use items. All with just a few lines of code.\n\n```C#\nusing UnityEngine;\nusing CleverCrow.Fluid.ElasticInventory;\n\npublic class PlayerInventory : MonoBehaviour {\n    public InventoryHelper inventory;\n    public ItemEntryWeapon weapon;\n    \n    // Access your currency easily at any time\n    public int Gold =\u003e inventory.Instance.Get(\"gold\")?.Quantity ?? 0;\n        \n    // Ability to implement simple or complex purchasing logic\n    public void BuyItem (ItemDefinition definition) {\n        if (Gold \u003c definition.cost) return;\n        \n        // Perform inventory CRUD with IDs or definitions\n        inventory.Instance.Add(definition);\n        inventory.Instance.Remove(\"gold\", definition.cost);\n    }\n        \n    public void EquipWeapon (string weaponEntryId) {\n        // Use a custom weapon entry here to add properties like damage, durability, etc.\n        weapon = inventory.Instance.GetEntry(weaponEntryId) as ItemEntryWeapon;\n    }\n    \n    public void UseItem (ItemDefinition definition) {\n        inventory.Instance.Remove(definition);\n        \n        // Use() is a custom method we've added. Heal a player, trigger an ability, whatever you want\n        definition.Use();\n    }\n}\n```\n\nThe above example assumes that you've created custom definitions and logic for your inventory. As Elastic Inventory's implementation is completely up to you, it serves as a bare-bones framework. Let's set up the ability to create items and make your first inventory in the [Getting Started Guide](#getting-started-guide).\n\n## Table of Contents\n\n- [Getting Started Guide](#getting-started-guide)\n    * [Important Architecture Concepts](#important-architecture-concepts)\n    * [Example Store](#example-store)\n- [Documentation](#documentation)\n    * [Inventory Instance](#inventory-instance)\n        + [Add item(s)](#add-items)\n        + [Remove item(s)](#remove-items)\n        + [Get item(s)](#get-items)\n        + [Get All Items](#get-all-items)\n        + [Has items](#has-items)\n        + [Events](#events)\n        + [Sorting items](#sorting-items)\n        + [Saving and Loading](#saving-and-loading)\n        + [Custom Implementation](#custom-implementation)\n    * [Inventory Helper](#inventory-helper)\n        + [Save and Load](#save-and-load)\n    * [Item Database](#item-database-1)\n        + [Get an item definition](#get-an-item-definition)\n        + [Save and Load](#save-and-load-1)\n        + [Manual saving and loading](#manual-saving-and-loading)\n        + [Globally Access The Item Database](#globally-access-the-item-database)\n        + [Syncing Missing Items](#syncing-missing-items)\n        + [Repairing IDs](#repairing-ids)\n            - [Modifying IDs in Production](#modifying-ids-in-production)\n- [Recipes](#recipes)\n    * [Custom Item Definitions](#custom-item-definitions)\n        + [Custom Item Entries](#custom-item-entries)\n    * [Creating Unique Items](#creating-unique-items)\n    * [Saving and Loading](#saving-and-loading-1)\n    * [Swapping items between inventories](#swapping-items-between-inventories)\n        + [Moving custom entries with stackable items](#moving-custom-entries-with-stackable-items)\n- [Developers Guide](#developers-guide)\n\n## Getting Started Guide\n\nElastic Inventory is used through [Unity's Package Manager](https://docs.unity3d.com/Manual/CustomPackages.html). In order to use it you'll need to add the following lines to your `Packages/manifest.json` file. After that you'll be able to visually control what specific version of Elastic Inventory you're using from the package manager window in Unity. This has to be done so your Unity editor can connect to NPM's package registry.\n\n```json\n{\n  \"scopedRegistries\": [\n    {\n      \"name\": \"NPM\",\n      \"url\": \"https://registry.npmjs.org\",\n      \"scopes\": [\n        \"com.fluid\"\n      ]\n    }\n  ],\n  \"dependencies\": {\n    \"com.fluid.elastic-inventory\": \"1.0.1\"\n  }\n}\n```\n\nNext you'll be greeted with a configuration wizard. Run it and you'll be able to create items by selecting the `ElasticInventory/Resources/ItemDatabase` asset and clicking the edit button. \n\nBefore you create an item, we recommend customizing the automatically generated item definition at `ElasticInventory/ItemDefinition` to your needs. This will allow you to add your own custom fields to items. Add a `cost` field to the auto generated definition.\n\n```C#\npublic class ItemDefinition : ItemDefinitionBase {\n    public int cost;\n}\n```\n\nNow all items will have a cost field you can use to buy and sell items.\n\nAdd a gold item to the `ItemDatabase` by clicking \"Add\". This will be used to purchase items. Make sure you set the definition `id` to `\"gold\"` in the inspector (defaults to a randomly generated unique ID). I added an extra image field, you wont need to do that.\n\n![Gold Item](images/gold.png)\n\nAlso add a few quick items to buy such as a Mine Key and Longsword with a specified cost. We'll use these to purchase items for a player inventory. Here is an example of what that might look like if you added a lot of items.\n\n![Item Example](images/item-example.png)\n\nNow add an `InventoryHelper` to a GameObject in a scene. This will automatically handle generating and maintaining an inventory for you. Add the gold to the starting items. Make sure you have enough gold to buy the items you want.\n\n![Inventory Helper](images/inventory-helper.png)\n\nLast but not least, we need a script that facilitates item purchases. Let's create a script that automatically buys an item on `Start` with the logic we just wrote.\n\n```C#\nusing UnityEngine;\nusing CleverCrow.Fluid.ElasticInventory;\nusing System.Collections.Generic;\n\npublic class PlayerInventory : MonoBehaviour {\n    public InventoryHelper inventory;\n    public List\u003cItemDefinition\u003e itemsToBuy;\n    \n    void Start () {\n        foreach (var item in itemsToBuy) {\n            inventory.Instance.Remove(\"gold\", item.cost);\n            inventory.Instance.Add(item);\n        }\n    }\n}\n```\n\nAdd the script, then attach the InventoryHelper to it and run the game. Notice that the item list on the InventoryHelper automatically updates its contents when run. This live debugging tool allows you to see what's in your inventory at any time.\n\n![inventory-final.png](images%2Finventory-final.png)\n\nSome of your names might differ from the above image. But when you run your UI, it should resemble this image.\n\nCongratulations! You now have a fully functioning inventory. Refer to the guides and docs below for advanced usage.\n\n### Important Architecture Concepts\n\nBefore you delve deeper, we recommend reading the following core concepts. These are the architectural patterns/concepts that drive Elastic Inventory.\n\n#### Item Database \n\nThe item database is a collection of item definitions. It's a scriptable object that can be edited in the Unity inspector. It's used to create and edit item definitions. At runtime a copy is lazy loaded for use by your inventory scripts.\n\n#### Item Entry\n\nAn item entry is a reference to a living item in your inventory. It contains a reference to the item definition, timestamps, quantities, and other runtime specific data. It also contains a unique ID that can be used to reference the item in the inventory. Any data edited here will be automatically saved and loaded by the item entry data resolver. \n\n#### Item Definition\n\nAn item definition is a template for an item. They form the backbone of the item entries' implementation. It contains a unique ID, a name, and any custom properties you've added to the definition. Note that definitions are static - they should never be edited at runtime. If you need to edit an item at runtime, use an item entry. Definitions can be stackable (default behavior) or unique (only one per stack).\n\n### Example Store\n\nWe strongly recommend running the example store in the Assets/Examples/Shop folder. It's a fully functional store with a player and shop inventory. It demonstrates saving, loading, buying items, custom properties, and more, all with an easy-to-use interface.\n\n[![Example Store](images/example-store.png)](https://github.com/ashblue/unity-elastic-inventory/tree/develop/Assets/Examples/Shop)\n\nTo run it download/clone this repo and run the corresponding scene.\n\n## Documentation\n\n### Inventory Instance\n\nThe inventory instance is a non-implementation specific representation of an inventory. It's a simple class that contains a list of items and a few helper methods. It's also serializable so it can be saved and loaded.\n\n#### Add item(s)\n\nThere are multiple ways to add an item. By definition, definition ID, or entry. Note that all `Add` methods return an `IItemEntryReadOnly` interface that can be used to reference the item in the inventory. See the corresponding interface for more information.\n    \n```C#\n// Add by definition reference\nvar entry = inventory.Instance.Add(definition, 2);\nDebug.Log(entry.Id); // Unique ID of the entry\n\n// Add by definition ID. Note you must have a definition with the ID \"sword\" in your database\ninventory.Instance.Add(\"sword\", 1);\n\n// Entry should be a reference to an existing entry. The reference will be added to the inventory.\n// Primarily used for moving items between inventories and unique items\n// Make sure the entry is removed from the original inventory before calling this\noldInventory.Instance.RemoveEntry(entry.Id);\ninventory.Instance.AddEntry(entry);\n```\n\n#### Remove item(s)\n\nThere are multiple ways to remove an item. By definition, definition ID, or entry. \n\nPlease note that unique items can only be removed by calling `RemoveEntry(ID)`. This is because a unique ID is required to remove an item when there are potentially multiple entries.\n\n```C#\n// Remove by definition reference\ninventory.Instance.Remove(definition, 1);\n\n// Remove by definition ID. Note you must have a definition with the ID \"gold\" in your database. \ninventory.Instance.Remove(\"gold\", 202);\n\n// Remove by entry ID reference. Note that every entry has a unique ID\ninventory.Instance.RemoveEntry(\"my-entry-id\");\n```\n\n#### Get item(s)\n\nThere are multiple ways to get an item entry. By definition, definition ID, or entry. If an item doesn't exist you will receive a `null` value.\n\n```C#\n// Get by definition reference\ninventory.Instance.Get(definition);\n\n// Get by definition ID. Note you must have a definition with the ID \"gold\" in your database.\ninventory.Instance.Get(\"gold\");\n\n// Get by entry reference\ninventory.Instance.GetEntry(\"my-entry-id\");\n```\n\n#### Get All Items\n\nYou can retrieve all items in an inventory. You can also specify an optional `definitionType` and/or `category` to filter the results.\n\n```C#\n// Get all items\ninventory.Instance.GetAll();\n\n// Get all items of a specific definition type\nvar type = typeof(GearDefinition);\ninventory.Instance.GetAll(definitionType: type);\n\n// Get all items of a specific category\ninventory.Instance.GetAll(category: \"weapon\");\n\n// Get all items of a specific definition type and category\ninventory.Instance.GetAll(definitionType: type, category: \"weapon\");\n```\n\n#### Has items\n\nYou can easily check if an item exists by using a definition, definition ID, or entry ID.\n\n```C#\n// Check by definition reference\ninventory.Instance.Has(definition, 1);\n\n// Check by definition ID. Note you must have a definition with the ID \"gold\" in your database.\ninventory.Instance.Has(\"gold\", 202);\n\n// Check by entry reference ID\ninventory.Instance.HasEntry(\"my-entry-id\");\n```\n\n#### Events\n\nSeveral events will automatically fire whenever an inventory is edited. This is extremely useful for UI updates and quests that require you to gather items. You can subscribe to these events with the following snippets.\n\n```C#\n// Subscribe to item added event\ninventory.Instance.Events.ItemAdded.AddListener((item) =\u003e {\n    Debug.Log(\"Item added: \" + item.Definition.DisplayName);\n});\n\n// Subscribe to item removed event\ninventory.Instance.Events.ItemRemoved.AddListener((item) =\u003e {\n    Debug.Log(\"Item removed: \" + item.Definition.DisplayName);\n});\n\n// Subscribe to item quantity changed event\n// Note this will fire when an item is added or removed\ninventory.Instance.Events.ItemChanged.AddListener((item) =\u003e {\n    Debug.Log(\"Item quantity changed: \" + item.Definition.DisplayName);\n});\n```\n\nAs with all event subscriptions, it is recommended to unsubscribe when the object is destroyed. The easiest way to do this is subscribe to the event with a method reference. Then you can unsubscribe with the same method reference when you're done.\n\n```C#\ninventory.Instance.ItemAdded.RemoveListener(methodReferenceHere);\n```\n\n#### Sorting items\n\nYou can sort a list from GetAll in place by calling Sort on it. Sorting options include primary sort, secondary sort, order, and secondary order.\n\n```C#\nvar items = inventory.Instance.GetAll();\n\n// Sort by category, then alphabetical\ninventory.Instance.Sort(\n    items: items, \n    sort: ItemSort.Category,\n    sortSecondary: ItemSort.Alphabetical,\n    orderSecondary: SortOrder.Ascending,\n);\n```\n\nYou can also sort by a custom category order. This is useful if you want to sort multiple forms of gear or items in a specific order.\n\n```C#\nvar items = inventory.Instance.GetAll();\n\nvar customCategorySort = new List\u003cCategorySort\u003e {\n    new(\"Weapons\", 0),\n    new(\"Armor\", 1),\n    new(\"Consumables\", 2),\n    new(\"Story\", 3),\n};\n\ninventory.Instance.Sort(\n    items: items, \n    sort: ItemSort.Category,\n    customCategory: customCategorySort,\n);\n```\n\n\n#### Saving and Loading\n\nYou can save and load an inventory instance with the following snippets. This should only be done if you wish to create your own implementation of `InventoryInstance` without using the `InventoryHelper`. It's recommended you use the `InventoryHelper` class to save and load inventories for simplicity.\n\n```C#\n// Save an inventory instance\nvar save = inventory.Instance.Save();\n\n// Load an inventory instance\nvar inventoryInstance = new InventoryInstance(ItemDatabase.Current);\ninventoryInstance.Load(save);\n```\n\n#### Custom Implementation\n\nYou can create your own inventory instances with a custom implementation separate from an Inventory Helper. This will give you full granular control. See the `InventoryInstance` class and test file for more information.\n\n### Inventory Helper\n\nThe InventoryHelper is a light wrapper that automatically manages a simple implementation of an inventory instance for you with a lazy loaded [database](https://github.com/ashblue/fluid-database). It's designed to only include the minimal logic required to get an inventory up and running. If you need more control, re-implement this instead of overriding it.\n\n#### Save and Load\n\nWhen calling `Save()` the inventory helper will automatically write data to a `GlobalDatabaseManager` singleton for you. It uses the ID in the inspector to generate a unique key.\n\n```C#\ninventoryHelper.Save();\n```\n\nThere is no `Load` method as the inventory helper will automatically load the inventory from the database every time it's initialized.\n\n### Item Database\n\nThe item database is a container for all item definitions. When initially called at runtime a copy is created and stored in memory. That said you should not try to edit your item definition database at runtime.\n\n#### Get an item definition\n\nYou can get an item definition by ID. If an item definition doesn't exist you will receive a `null` value.\n\n```C#\nvar itemDefinition = ItemDatabase.Current.Get(\"gold\");\n```\n\n#### Save and Load\n\nTo save the database you only need to call `Save()`. This will write the database to a `GlobalDatabaseManager` singleton. Doing this is strongly recommended as the database keeps track of the total inventory item count in your project. The item count is used for specific kinds of sorting. If you notice issues with create at and updated at timestamps when sorting, it's likely because you haven't saved your database.\n\n```C#  \nItemDatabase.Current.Save();\n```\n\nIf `_autoLoad` is checked you won't need to manage loading your database. As it will automatically pull from the `GlobalDatabaseManager` singleton. If you want to manually load your database you can do so with the following snippet.\n\n```C#\nItemDatabase.Current.Load();\n```\n\n#### Manual saving and loading\n\nIf you want to manage the save and load of your database by hand, there is a manual save and load method you can use.\n    \n```C#\nvar save = ItemDatabase.Current.SaveManual();\nItemDatabase.Current.LoadManual(save);\n```\n\n#### Globally Access The Item Database\n\nYou can access the item database from anywhere in your code with the following snippet. It'll create a runtime instance if one doesn't already exist.\n\n```C#\nvar itemDatabase = ItemDatabase.Current;\n```\n\n#### Syncing Missing Items\n\nIf your item definitions get out of sync. You can repair them by clicking the \"Sync\" button on the database. This will clear all your definition references and rebuild them from the Unity's Asset Database. Useful if you're manually editing item definitions in the project window.\n\n#### Repairing IDs\n\nDuplicate item definition IDs can cause issues in your project. Therefore, it is strongly recommended to repair the IDs if you clone or copy an item definition.\n\nElastic Inventory comes with a button on the database object called \"Repair IDs.\" It will automatically repair all duplicate IDs and print the details to the logs. We suggest reviewing the logs. As you may need to adjust what IDs have been repaired to ensure save and load data doesn't get corrupted for items already in production.\n\n##### Modifying IDs in Production\n\nKeep in mind item definition IDs are used to save and load your inventory. If you change IDs that existing saves are using, you will need to write your own migration code. Elastic inventory does not come with a tool to fix this. It's recommended to NEVER change item definition IDs that users are saving and loading in production.\n\n## Recipes\n\nThe following examples demonstrate solutions to common tasks or situations you may encounter.\n\n### Custom Item Definitions\n\nTo add unique serialized fields to your items, such as a weapon with damage and energy cost, you can create custom item definitions. Here's a code snippet to illustrate this:\n\n```C#\nusing CleverCrow.Fluid.ElasticInventory;\nusing UnityEngine;\n\n// This attribute is required to register the item definition with the database and to give it a dropdown name\n[ItemDefinitionDetails(\"Weapon\")]\npublic class ItemDefinitionWeapon : ItemDefinitionBase {\n    [SerializeField]\n    private int _damage;\n\n    [SerializeField]\n    private int _energyCost;\n\n    // Add this category to the database's category list for filterability in the database editor\n    public override string Category =\u003e \"Weapon\";\n    \n    public override bool Unique =\u003e true;\n    public int Damage =\u003e _damage;\n    public int EnergyCost =\u003e _energyCost;\n}\n```\n\n#### Custom Item Entries\n\nTo create a custom item entry, extend the ItemEntryBase class. This allows you to add custom fields to the item entry. For instance, to add a level and durability field, refer to the following snippet:\n\n```C#\nusing CleverCrow.Fluid.ElasticInventory;\n\npublic class ItemEntryWeapon : ItemEntryBase {\n    public int Level { get; set; } = 1;\n    public int Durability { get; set; } = 1000;\n}\n```\n\nTo save and load the new entry fields above, create an ItemEntryDataResolver, a class that handles serialization and deserialization. This class will manage saving and loading your custom entry fields:\n\n```C#\nusing CleverCrow.Fluid.ElasticInventory;\n\n[System.Serializable]\npublic class ItemEntryDataResolverWeapon : ItemEntryDataResolverBase\u003cItemEntryWeapon\u003e {\n    public int level;\n    public int durability;\n\n    protected override void OnSave (ItemEntryWeapon itemEntry) {\n        level = itemEntry.Level;\n        durability = itemEntry.Durability;\n    }\n\n    protected override void OnLoad (ItemEntryWeapon itemEntry) {\n        itemEntry.Level = level;\n        itemEntry.Durability = durability;\n    }\n\n    // Data resolvers are reused by each definition. It's recommended to reset data here to avoid data leakage between saving and loading items\n    protected override void OnReset () {\n        level = 0;\n        durability = 0;\n    }\n}\n```\n\nLastly, inform your custom ItemDefinition about the new entry and data resolver. This can be achieved by adding the following logic:\n\n```C#\npublic class ItemDefinitionWeapon : ItemDefinitionBase {\n    public override IItemEntryDataResolver DataResolver =\u003e new ItemEntryDataResolverWeapon();\n    \n    public override IItemEntry CreateItemEntry (IItemDatabase database, int quantity = 1, string id = null, int? createdAt = null, int? updatedAt = null) {\n        // We have to initialize a new implementation of the entry here\n        // This is because the database doesn't know about our custom entry type\n        var entry = new ItemEntryWeapon();\n        entry.Setup(database, this, quantity, id, createdAt, updatedAt);\n\n        return entry;\n    }\n}\n```\n\n### Creating Unique Items\n\nBy default, items are stackable (adding multiple entries will increase the quantity). However, if you want to create a unique item that generates new entry every time it's added, override the `Unique` property on the item definition. This can be useful for gear, abilities, tools, or other items that should not stack:\n\n```C#\nusing CleverCrow.Fluid.ElasticInventory;\n\npublic class MyUniqueItem : ItemDefinitionBase {\n    public override bool Unique =\u003e true;\n}\n```\n\n### Saving and Loading\n\nSaving and loading is handled automatically by the `GlobalDatabaseManager` singleton (unless manually implemented, which is not recommended). Nonetheless, you still need to restore the `GlobalDatabaseManager` save data. Here's a class that quickly enables saving and loading. Note, there are various ways to achieve this, and you may need to adjust the following code to suit your project:\n\n```C#\nusing System.Collections.Generic;\nusing CleverCrow.Fluid.Databases;\nusing CleverCrow.Fluid.ElasticInventory;\nusing UnityEngine;\n\n/// \u003csummary\u003e\n/// Please note this script must execute before the inventory helper and item database scripts\n/// You'll need to manually set the index in the script execution order window\n/// https://docs.unity3d.com/Manual/class-MonoManager.html\n/// \u003c/summary\u003e\npublic class InventorySaveHelper : MonoBehaviour {\n    const string SAVE_KEY = \"GLOBAL_DATABASE_SAVE\";\n    \n    // Attach all your game's inventories here\n    [SerializeField]\n    List\u003cInventoryHelper\u003e _inventories;\n\n    void Awake () {\n        if (!PlayerPrefs.HasKey(SAVE_KEY)) return;\n\n        // Restore the inventory database\n        var save = PlayerPrefs.GetString(SAVE_KEY);\n        GlobalDatabaseManager.Instance.Load(save);\n    }\n\n    // Call this method to save all inventory data\n    public void Save () {\n        _inventories.ForEach(i =\u003e i.Save());\n        ItemDatabase.Current.Save();\n\n        var save = GlobalDatabaseManager.Instance.Save();\n        \n        // We're using PlayerPrefs to quickly save the data, but you can use whatever you want here\n        PlayerPrefs.SetString(SAVE_KEY, save);\n    }\n}\n```\n\n### Swapping items between inventories\n\nItem transfer between inventories is a frequent task. For instance, you may want to move an item from a player's inventory to a chest. The following snippet demonstrates how to do this:\n\n```C#\npublic void TransferItem (IItemEntryReadOnly item, int quantity, IInventoryInstance from, IInventoryInstance to) {\n    from.RemoveEntry(item.Id, quantity);\n    to.AddEntry(item);\n}\n\ninventory.TransferItem(entry, 1, playerInventory, chestInventory);\n```\n\nIn this example we're using the `RemoveEntry` and `AddEntry` methods to move the item. This approach is recommended when dealing with entries, as it prevents the loss of custom entry data (like durability and level) on unique items.\n\n#### Moving custom entries with stackable items\n\nNote that stackable items will not transfer custom entry data. This is by design, as the `Add` methods only modify the existing quantity of a stack. If you want to transfer custom entry data on stacks, you must manually handle it.\n\nNot transferring stackable item entry data is by design. For instance, consider a healing flask with a quantity of 10 and a custom entry level of 2 to increase the healing amount. In this case, the player is buying/selling charges, not flasks. The flask bottle serves as a container. Therefore, when the player purchases 5 charges from a store, the default custom entry level of 1 in the store should not be transferred.\n\n## Developers Guide\n\nHow to run the development environment and access various development tools.\n\n### Releases\n\nArchives of specific versions and release notes are available on the [releases page](https://github.com/ashblue/unity-elastic-inventory/releases).\n\n### Nightly Builds\n\nTo access nightly builds of the `develop` branch that are package manager friendly, you'll need to manually edit your `Packages/manifest.json` as so. \n\n```json\n{\n    \"dependencies\": {\n      \"com.fluid.elastic-inventory\": \"https://github.com/ashblue/unity-elastic-inventory.git#nightly\"\n    }\n}\n```\n\nNote that to get a newer nightly build you must delete this line and any related lock data in the manifest, let Unity rebuild, then add it back. As Unity locks the commit hash for Git urls as packages.\n\n### Development Environment\n\nIf you wish to run the development environment you'll need to install the [Node.js](https://nodejs.org/en/) version in the [.nvmrc](.nvmrc) file. The easiest way to do this is install [NVM](https://github.com/nvm-sh/nvm) and run `nvm use`. \n\nOnce you've installed Node.js, run the following from the root once.\n\n`npm install`\n\nIf you wish to create a build run `npm run build` from the root and it will populate the `dist` folder.\n\n#### Making Commits\n\nAll commits should be made using [Commitizen](https://github.com/commitizen/cz-cli) (which is automatically installed when running `npm install`). Commits are automatically compiled to version numbers on release so this is very important. PRs that don't have Commitizen based commits will be rejected.\n\nTo make a commit type the following into a terminal from the root.\n\n```bash\nnpm run commit\n```\n\n### How To Contribute\n\nPlease see the [CONTRIBUTIONS.md](CONTRIBUTING.md) file for full details on how to contribute to this project.\n\n---\n\nThis project was generated with [Oyster Package Generator](https://github.com/ashblue/oyster-package-generator).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashblue%2Funity-elastic-inventory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fashblue%2Funity-elastic-inventory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashblue%2Funity-elastic-inventory/lists"}