Skip to main content

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 saysUse it for
Container Type (FGameplayTag)What kind it is — a hotbar, a stashLooking one up: GetContainer(Tag)
Container Id (FGuid)Which instance it isNaming 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.

FieldWhat it decides
Container TagIts identity. Everything finds and targets it by this. Required.
Display Name / Description / IconWhat the player sees: a tab label, a window title, a transfer prompt.
Container TagsFree-form traits for your own queries. The framework never reads them.
Container ClassThe runtime UEDContainer subclass. Only needed for container-wide behaviour.
LayoutHow slots are addressed — list, slot or grid. Empty means a plain bag with no placement.
Slot Count ModeCapacity from the layout, or from a GAS attribute so a perk can grow the bag.
Swap PolicyWhat a drop onto an occupied slot does: swap, swap only if both sides accept, or refuse.
Item QueryWhich items it will take at all, over the item's category and tags. Empty means anything.
PriorityHow eagerly it claims an item nobody routed. Higher goes first.
RulesAcceptance 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 has exactly one source

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:

  1. Content Browser → Blueprint Class, parent EDContainerComponent (or EDInventoryManagerComponent).
  2. In Class Defaults, set the Container Definition — the same asset you would set on an instance.
  3. 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.

Editing Class Defaults from code

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​