Containers and layouts
A container is the thing that holds items and the thing gameplay talks to. Components are just ways of giving an actor one.
The container itself
UEDContainer is a UObject, not a component. That is what lets the same logic serve a chest, a
character's hotbar, and the grid inside a backpack an item brought with it. It finds its owning actor
by walking the outer chain and derives authority from that actor.
The action API lives here — TryAddItem, TryRemoveItem, TryTransferItem, RequestSort,
RequestTransaction and the rest. Whatever gave you the container, you act on the container.
UEDContainer* Chest = ChestActor->GetContainer();
Chest->TryAddItem(Definition, 3); // authority
Chest->RequestSort(EEDSortMode::ByName); // safe anywhere; routed to the server from a client
Identity: type and id
Every container carries two different answers to "which one is this?":
| What it says | Use it for | |
|---|---|---|
Container Type (FGameplayTag) | What kind it is — a hotbar, a stash | Looking one up: GetContainer(Tag) |
Container Id (FGuid) | Which instance it is | Naming one exactly, when several share a type |
Both replicate. Matching by type is hierarchical, so asking for Inventory.Container finds an
Inventory.Container.Hotbar.
Two containers of the same type are allowed — a character wearing two quivers has two — so
GetContainer(Tag) returns the first, GetContainersByTag returns them all, and GetContainerById
returns exactly one.
Describing a container as data
UEDContainerDefinition is the asset. One asset can describe many live containers.
| Field | What it decides |
|---|---|
| Container Tag | Its identity. Everything finds and targets it by this. Required. |
| Display Name / Description / Icon | What the player sees: a tab label, a window title, a transfer prompt. |
| Container Tags | Free-form traits for your own queries. The framework never reads them. |
| Container Class | The runtime UEDContainer subclass. Only needed for container-wide behaviour. |
| Layout | How slots are addressed — list, slot or grid. Empty means a plain bag with no placement. |
| Slot Count Mode | Capacity from the layout, or from a GAS attribute so a perk can grow the bag. |
| Swap Policy | What a drop onto an occupied slot does: swap, swap only if both sides accept, or refuse. |
| Item Query | Which items it will take at all, over the item's category and tags. Empty means anything. |
| Priority | How eagerly it claims an item nobody routed. Higher goes first. |
| Rules | Acceptance rules: weight caps, tag filters, your own. |
Editor validation refuses a definition with no identity tag, because that failure is otherwise silent at runtime.
The three layouts
A layout decides how slots are addressed and where an item may sit. It is an FInstancedStruct on the
definition, so a container's topology is data.
List
FEDListLayoutConfig — N numbered slots, one item each. Hotbars, action bars, simple bags.
[0][1][2][3][4][5][6][7][8]
Slot
FEDSlotLayoutConfig — a fixed set of named slots, each with its own filter. Equipment paperdolls.
Head ← accepts Inventory.Slot.Head
Chest ← accepts Inventory.Slot.Chest
OffHand← accepts anything (empty filter)
Auto-placement prefers a slot that names what it takes over one that takes anything, whatever order they were authored in. Otherwise a single permissive slot swallows the first item auto-equipped and the slot it belonged in stays empty.
Grid
FEDGridLayoutConfig — a width × height board where an item covers cells according to its Size
fragment, with rotation and non-rectangular shapes.
┌───┬───┬───┬───┐
│ ▓ │ ▓ │ │ │ a 2×2 item, an L-shaped item,
│ ▓ │ ▓ │ █ │ │ and free cells
├───┼───┼───┼───┤
│ │ █ │ █ │ │
└───┴───┴───┴───┘
Grids compact row-major when sorted and auto-rotate an item that only fits the other way round.
Capacity comes from the layout: a 6×4 grid holds 24, a list of 9 holds 9, a paperdoll holds one per named slot. A container with no layout is unlimited. There is no separate slot-count field beside the layout, because two limits that can disagree is a bug waiting to happen.
Rules
Rules are FInstancedStructs on the container, consulted at a single acceptance gate — which means a
dry run (EvaluateAddItem) and the real thing can never disagree.
Shipped: Locked, Allowed Tags, Forbidden Tags, and Weight Limit (in the Weight module).
A rule that depends on who is asking — ownership, guild rank, a moderator tier — is deliberately not shipped: those differ enough per game that writing one is easier than bending someone else's. The instigator reaches both the validate and the execute stage, so your rule can use it. See Extending.
Giving an actor a container
Two ways, and the choice is about how many:
UEDInventoryManagerComponent — one component, many containers, described by assets, and
containers can come and go at runtime. This is what a character wants. See
The inventory manager.
UEDContainerComponent — one component, one container. Point its Container Definition at
the same kind of asset the manager uses and the chest has storage. This is what a chest wants: no
routing to do, nothing to gain from the manager.
The component used to carry its own slot count, tag, tags, rules, layout and container class — a second way of describing a container that did not quite agree with the first. It has one property now, and it is the same asset everything else already reads.
Both derive from UEDInventoryRouteComponent, which is the piece that carries a client's request to
the server.
When a Game Feature adds the component
GameFeatureAction_AddComponents adds a class, never a configured instance — so if a Game
Feature is what puts the inventory on your pawns, bots and controllers, the configuration has to live
in the class. Both components are Blueprintable, so that class can be a Blueprint:
- Content Browser → Blueprint Class, parent
EDContainerComponent(orEDInventoryManagerComponent). - In Class Defaults, set the Container Definition — the same asset you would set on an instance.
- Name that Blueprint in the Game Feature action's component list.
The class being the configuration is also what makes it correct on both machines. These components
replicate, and UGameFrameworkComponentManager creates a replicated component on the authority
only; clients receive it as a replicated subobject. The Blueprint's defaults are read from the
class on each machine rather than sent over the wire, and the container it builds replicates by the
ordinary path.
Writing to a Blueprint's class default object without recompiling leaves the object holding the new
value while instances are still built without it. The editor recompiles when a designer edits Class
Defaults; a commandlet or a test has to call FKismetEditorUtilities::CompileBlueprint after
writing.
Where next
- The inventory manager
- Placement and routing — how a container is chosen
- Nested containers — containers that belong to an item