Skip to main content

Items in the world

The framework describes what an item looks like in the world. Spawning it, picking it up and dropping it are your game's decisions, and deliberately so — "pick up" means something different in a survival game and a shooter.

The World Model fragment

FEDWorldModelFragment says how an item appears outside an inventory:

FieldMeaning
Model TypeStatic mesh, skeletal mesh, or a spawned actor class
Static Mesh / Skeletal Mesh / Actor ClassWhat to show
Override MaterialAn instance override, so one mesh serves several items
Offset / Rotation / ScaleThe resting transform
Simulate PhysicsWhether the dropped item falls

An item with no World Model fragment has no ground representation. That is fine for something that can never be dropped.

Building a pickup

The minimum: an actor holding a definition and a count, that gives them to whoever asks.

bool AMyPickup::GiveTo(AActor* Collector)
{
if (!HasAuthority())
{
return false;
}

UEDInventoryManagerComponent* Inventory = UEDInventoryManagerComponent::Find(Collector);
if (!Inventory || !Inventory->TryAddItem(ItemDefinition, StackCount))
{
return false; // no room; leave the pickup where it is
}

Destroy();
return true;
}

TryAddItem is all-or-nothing, so a failure means nothing was taken and the pickup is still valid. Never destroy the actor before the add succeeds.

Dropping

Dropping is the same in reverse: take the entry out, then spawn something carrying its definition and count.

void AMyCharacter::DropItem(FEDItemHandle Handle)
{
if (!HasAuthority()) { return; }

const FEDItemEntry* Entry = nullptr;
UEDContainer* Holder = Inventory->FindItem(Handle, Entry);
if (!Holder || !Entry) { return; }

// Read what you need BEFORE mutating: a failed resolve must never destroy the item.
const int32 Count = Entry->StackCount;
UEDItemDefinition* Definition = UEDItemFunctionLibrary::ResolveDefinition(Entry->DefinitionId);
if (!Definition) { return; }

if (Holder->TryRemoveItem(Handle))
{
SpawnPickup(Definition, Count);
}
}

The order matters. Resolve first, remove second, spawn third — so a definition that fails to resolve costs you nothing rather than an item.

Dropping needs the Asset Manager

Rebuilding a world item from an entry means turning a FPrimaryAssetId back into a definition. If your item folders are not registered, pickup works and dropping produces a warning and nothing else. See Installation.

Chests, corpses, and other world containers

An actor with a UEDContainerComponent is a container in the world. Configure its layout and rules in the details panel; that is the whole setup.

Two things make it behave properly for a player standing at it:

Open a session so the screen closes when they walk away:

PlayerInventory->OpenSession(ChestActor->GetContainer());

Let requests route. A chest is server-owned, so a client's request on it would be dropped by the engine. UEDContainer::RequestTransaction finds a component the client does own and sends it through that instead — automatic, but worth knowing when you are reading a call stack.

Loot in a chest

The Loot module rolls a table into a container:

const TArray<FEDLootRollResult> Roll = UEDLootStatics::RollLootTable(this, LootTable, Budget);
UEDLootStatics::GiveLoot(ChestActor->GetContainer(), Roll);

Rolls come from the world subsystem's seeded stream, so a fixed seed reproduces a chest exactly — which is what makes loot testable. See Trading and loot.

Where next