Quick Start
This guide creates two regular inventories that support dragging items between each other.
The same setup is already implemented in the first example, where you can see the final result.
Even in a basic scenario, you usually need a little integration code for your own data. In this guide that means:
ItemSOas your item dataItemSOAdapteras the representation for the inventory systemSimpleBindingas the bridge between UI and your data list
Step 1. Prepare The Scene
Inventories are plain uGUI, so they live on a UI canvas.
-
Create a
Canvasfor the inventories if the scene does not have one yet.In the
Hierarchywindow, right-click empty space and chooseUI → Canvas.Unity creates an
EventSystemobject along with theCanvas. For a quick start, leave theCanvasatRender Mode=Screen Space - Overlay. -
Add
DragAndDropManagerto the scene.Find
Prefabs/DragCanvas.prefabin theProjectwindow and drag it into empty space in theHierarchy— it should become a root object of the scene, next to yourCanvas.DragCanvashas its ownCanvaswithSorting Order = 100, which is what keeps the dragged item rendered above the rest of the interface. BesidesDragAndDropManager, the prefab carriesInputEventRouterandDragVisualPresenter. The scene needs exactly one such object: it manages all transfer operations and owns the visual of the item "in hand". -
Check the
EventSystem.If the
Hierarchyhas none, right-click empty space and chooseUI → Event System.Select
EventSystemand check in theInspectorwhich input module it carries:- legacy input project — it needs
StandaloneInputModule; - New Input System project — it needs
InputSystemUIInputModule.
The asset supports both.
DragAndDropManagerhas a minimal working action config by default. You can edit it or create your own copy, then assign it in the scene. - legacy input project — it needs
Step 2. Create Two Inventories
-
In the
Hierarchy, right-click theCanvasobject and chooseCreate Empty. Name the new objectBackpack.Because the parent is a
Canvas, Unity gives the object aRectTransform. If you want a background right away, chooseUI → Panelinstead ofCreate Empty. -
Give
Backpacka size and a position.A UI object has a
RectTransforminstead of aTransform, and afterCreate EmptyitsWidthandHeightare zero. Size is set here, not through scale:- select
Backpackand in theInspector, in theRectTransformcomponent, setWidth=540,Height=240; - position is easiest to set with the anchor presets button — the square with a cross in
the top-left corner of
RectTransform. Press it and pickmiddle centerfor a quick start, then move the object with thePos XandPos Yfields.
If you used
UI → Panel, it already stretches to the full screen — just set theWidthandHeightyou want the same way. - select
-
Right-click
Backpack, chooseCreate Emptyand name the objectSlotContainer.Stretch it over the whole
Backpack: press the anchor presets button and, holdingAltandShift, pick the bottom-rightstretch / stretchoption.Then press
Add Component → Layout → Grid Layout Groupand fill in its fields:Grid Layout GroupfieldValue Cell Size100×100— the slot size fromPrefabs/Slot.prefabSpacing5on X and YConstraintFixed Column CountConstraint Count5, so 10 slots form a 5 × 2 gridThis component is what arranges the slots into a grid.
-
Add the
UniversalInventorycomponent toBackpackand fill in the fields.In the Inspector they are split into collapsible groups:
Slot Setupgroup:Field Value Slot ContainerThe SlotContainerobject from step 3 — the parent the slots are created underSlot PrefabSlot prefab you want to use; Prefabs/Slot.prefabworks for a startInitial Slot CountFor example 10. That many slots are created inSlot Containeron startup. If you created them yourself, cache them with theCache SlotsbuttonStrategygroup — two unlabeled fields, each picked from a dropdown:What to pick Value top dropdown (inventory strategy) UniqueItemStrategyfor the simplest start, so each item occupies its own slotbottom dropdown (slot management) FixedSlotManagementSettingsfor a fixed number of slotsThe remaining groups (
Rules,Drop Policy,Placement) can stay untouched for a quick start. -
Duplicate
Backpackand create a second inventory, for exampleChest. Move them apart with thePos Xfield so both are visible at the same time.
Info
On startup, the inventory tries to find already created slots under Slot Container
and cache them. If there are not enough slots, it creates slots from Slot Prefab
up to Initial Slot Count. You can also create all slots manually in edit mode and
cache them with Cache Slots, so this operation does not happen during play.
Step 3. Define An Item Type
Suppose you have an item type:
[CreateAssetMenu(menuName = "Game/Item")]
public class ItemSO : ScriptableObject
{
[field: SerializeField] public string ItemName { get; private set; }
[field: SerializeField] public Sprite Icon { get; private set; }
}
To display this type in slots, create an adapter that implements IItemAdapter:
using UDND.Core;
using UnityEngine;
public class ItemSOAdapter : IItemAdapter
{
// Reference to your data type.
public readonly ItemSO Data;
// Constructor.
public ItemSOAdapter(ItemSO data) => Data = data;
// Required interface fields.
public string ItemId => Data.GetInstanceID().ToString();
public Sprite Icon => Data.Icon;
public string DisplayName => Data.ItemName;
}
Required field meanings:
ItemId— used to decide whether items can be merged into one slot forStackableandSeparableStacksstrategies.Icon— used to display the item image in the slot.DisplayName— used mainly in logs and some optional systems, such as the tooltip example. It can be an empty string.
Step 4. Add A Simple Binding
To show your data in slots, you need to give the system access to that data and define how it can interact with it. In real projects, these data sets usually live in player, character, or world-object scripts. In this example, the list is stored directly in the component.
using UDND.Core;
using UDND.DataBinding;
using System.Collections.Generic;
using UnityEngine;
public class SimpleBinding : ListInventoryDataBinding<ItemSO, ItemSOAdapter>
{
// Your data list.
[SerializeField] private List<ItemSO> _items;
// Required overrides.
protected override IReadOnlyList<ItemSO> GetItems() => _items;
protected override ItemSOAdapter CreateAdapter(ItemSO item) => new(item);
protected override void AddToData(ItemSOAdapter adapter) => _items.Add(adapter.Data);
protected override void RemoveFromData(ItemSOAdapter adapter) => _items.Remove(adapter.Data);
}
ListInventoryDataBinding is a DataBinding template for data stored as a list. When
inheriting from it, you specify your item type and its adapter type.
Required method meanings:
GetItems— used for initial data rendering.CreateAdapter— creates an adapter and passes it the required data.AddToData— called when an item is transferred into this inventory.RemoveFromData— called when an item is transferred out of this inventory.
Add this binding to both inventories or other objects in the scene.
Assign references to the corresponding inventories.
Each binding has its own _items list.
Info
In real projects, instead of a simple _items list, you will most likely interact
with your own scripts that store data. See examples for implementations of this pattern.
Step 5. Fill Starting Data
- Create a few
ItemSOassets. - Add them to
_itemsin yourSimpleBindingcomponents. - Run the scene.
If everything is configured correctly:
- both inventories show items
- an item can be dragged from one inventory to another
- backing data lists update automatically during transfer
What Happens Under The Hood
flowchart LR
A["Player drags an item"] --> B["<b>UniversalInventory</b> handles transfer"]
B --> C["Methods are called in <b>DataBinding</b>"]
C --> D["Your List<ItemSO> is updated"]
Common First-Project Mistakes
- the inventory was created as a 2D or plain scene object instead of UI inside a
Canvas: the Inspector shows aTransforminstead of aRectTransform BackpackorSlotContainerstill hasWidthandHeightof zero in itsRectTransform, so the inventory is invisible or sits somewhere unexpected- size was set through
Scaleinstead ofWidthandHeight DragCanvaswas placed inside your ownCanvas, so the dragged item disappears behind the interfaceSlot Containerpoints at the inventory itself instead of a child object with aGrid Layout GroupItemIddoes not match your stacking logic, so items unexpectedly merge or do not merge- there is no
DragAndDropManagerin the scene - there is no
EventSystemin the scene - the project uses legacy input, but
EventSystemhas noStandaloneInputModule - binding is connected to the wrong
UniversalInventory InventoryDataBindinghas no assigned inventory reference- data changes outside the pipeline, but
ReloadUI()is not called. Add aReloadUIcall in your DataBinding when data changes
See also:
- Examples — if you want to choose from all 6 demos
- Data Binding — if you need to understand lifecycle and extension points
- Placement Strategies — if you want to add your own strategy or slot management mode
- Troubleshooting — if the basic scene does not work on the first try