Loot Chests
Documentation Unreal Engine Player Combat Inventory Multiplayer
Chests, stashes and enemy loot keep their items in a UPC World Inventory that every nearby player sees. One press takes everything that fits, or opens the inventory screen with the chest beside it.
Set it up
5 minutes- 1
Make the chest
Create Actor BlueprintBP_MyChestwith Replicates ticked in Class Defaults. Add a collidable Static Mesh and a UPC World Inventory with ConfigInventoryConfig_UPC_LootChestand your Starting Items.DetailsUPCWorldInventoryUPC
Inventory
ConfigInventoryConfig_UPC_LootChestStarting Items5 Array elementsIndex [ 0 ]Item_UPC_PotionIndex [ 1 ]Item_UPC_PotionIndex [ 2 ]Item_UPC_PotionIndex [ 3 ]Item_UPC_RingIndex [ 4 ]Item_UPC_NecklaceAccess Radius300Access TagNoneYour chest, filled as the demo chest is: three potions, a ring and a necklace in thirty slots. - 2
Give it a Take All option
Add UPC Interactable with one Options element: Option IdTakeAll, Activation Input TagUPC.Input.Interact, Prompt VerbTake All, NameChest. Leave Payload (what the character plays first, such as a montage or delay) empty so the option fires at once (Interaction). - 3
Take everything on the option
Select UPCInteractable and press + beside On Option Interacted. It fires for each option the chest offers, so check the Option Id, then hand the chest to the interacting character's inventory:BP_MyChest · Take AllOn Option Interacted (UPCInteractable)InstigatorOptionBreak UPC Interaction OptionUPC Interaction OptionOption Id==BranchConditionTrueFalseGet Component by ClassTargetComponent ClassUPC InventoryReturn ValueUPCWorldInventoryRequest Take AllTarget is UPC InventoryTargetWorld Inventory - 4
Press Play and press E at the chest
PlaceBP_MyChestinLVL_UPC_Demo, press Play, and press E at it (a character of your own needs Interaction set up first). Everything that fits moves into your inventory.
Lock it, or set its reach
| Setting | Does |
|---|---|
| Access Radius | Distance from the actor's collision within which a character may take or put items, in cm (default 300; 0 is any distance). Keep it at least the interaction reach, 225 cm by default. |
| Access Tag | A tag the character's ability system must hold, such as a key for a locked chest; your own code adds it. Empty lets any character in reach use it. |
Lock a chest with the World Inventory's Access Tag, and leave the Access Tag on a container in the chest's config empty: the chest itself would have to hold it, and no character could reach the container.
Is Reachable By answers both for one character, with reason
UPC.Inventory.Refused.OutOfReach or NoAccess; a chest screen asks it to close as the player walks away.For an enemy's loot, spawn a loot actor where it fell. Keep a World Inventory off characters: code that looks up a character's inventory takes the first one it finds.
Open it beside the inventory screen
- Add a second option: Option Id
OpenInventory, Activation Input TagUPC.Input.Interact, VerbOpen, and a Delay payload of 0 seconds. Unlike Take All, this option needs a payload: the screen opens only for an option that has one. - Move Take All to
UPC.Input.Interact.Secondary, the F key.
BPC_UPC_InventoryScreens, on the demo's BP_UPC_PlayerController, opens the player's screen with the chest's items beside it when the payload starts. On Option Interacted then fires for Open too, where the Option Id check from the quick start keeps it from taking everything.To skip these steps, duplicate the demo's
BP_UPC_LootChest, which has both options, and change its Starting Items. Inventory Screens shows what each style's screen offers at a chest.Move items from a screen of your own
Call these on the player's inventory with the chest's World Inventory as a pin:
| Node | Does |
|---|---|
| Request Take All | Takes everything that fits; the rest stays in the chest. |
| Can Transfer | What moving Count units between the two would do (Place, Merge or Refused with a reason), for coloring a drop target. |
| Request Transfer | Moves those units as Can Transfer answers. |
No player's connection owns the chest, so players cannot rearrange its slots; only server code changes its layout. Read it like any inventory with Get Items in Container and On Layout Changed (Inventory Screens).
Debug it
Log LogUPCInventory Verbose logs each request the server turned down.AdvancedHow items move
- Request Take All goes through the chest in list order. Each stack lands as an add would, as a pickup does: the survival grid puts a key in Key Items and the rest in the case, and leaves what the case has no room for. With no Config, everything lands in the one list.
- A stack carrying stat tags moves whole or stays.
- The 225 cm reach is the UPC Interactor's Detection Radius (200) plus the UPC Interact Ability's Server Range Tolerance (25).
- Can Transfer takes an item in either inventory and a Destination in the other. Place splits part of a stack off; Merge moves as many units as the target stack has room for. Inventories never trade places, so an occupied place answers Occupied.
- The item that arrives is a new item of the same kind, with the same count and stat tags; a bag moves with what it holds. A whole stack on the belt or in hand stays with the player.
The demo
BP_UPC_LootChest (Demo/Interactables/LootChest, in the LVL_UPC_Demo hallway) is a replicating actor whose World Inventory uses InventoryConfig_UPC_LootChest (thirty slots under UPC.Inventory.Container.LootChest) and starts with three potions, a ring and a necklace. Open, on E, shows the chest beside the player's screen: all thirty slots, scrolling when they do not fit (WBP_UPC_ChestPanel on the survival grid and party RPG screens, a mirrored panel on the open world list). A right click on your own item stores it in the open chest, letting go of it first when the belt or a hand holds it; a weapon stays in hand when the chest is full and the message line reads Full. Take All, on F, calls Request Take All.MultiplayerWhat runs where
- The items reach every machine the actor reaches, so the actor must replicate. Everyone near a chest receives its entries, and a dormant chest wakes for each change.
- A Development build can log an ensure naming
SwapReferencesForDormancyonce, when a change wakes the chest as it goes dormant and a lost packet delays that moment for one player. Nothing is lost; set the chest's Net Dormancy to Awake to silence it. - The server checks every request: reach, Access Tag, that the units are still there, and that the receiving inventory takes them. A request it turns down changes nothing and sends no reply.
- Of two players reaching for the last potion, the first request gets it, and the second finds it gone; no listener sees the units in both places.
C++C++
UUPCWorldInventoryComponentis aUUPCInventoryComponentwhoseIsWorldInventory()answers true, so its list and items replicate to every machine rather than to an owning player.RequestTransfer,RequestTakeAllandCanTransferlive onUUPCInventoryComponentand take the world inventory as a typed parameter; one called on a world inventory itself is refused.IsReachableBy(Character, OutReason)measures with the distance the interaction confirms with.
AdvancedTroubleshooting
- The chest shows its items on the server only. Tick Replicates in its Class Defaults; the Output Log warns once.
- Take All or a transfer moves nothing. The character stands beyond Access Radius, lacks the Access Tag or has no room, or the call went to the World Inventory in place of the player's own.
- A bag in the chest shows none of its items. A world inventory opens no bags; the bag keeps its items until a player carries it where bags open. The Output Log warns once about a chest container with Opens Bags ticked.