Where does this custom inventory data "live" at runtime?

I can offer some insight in this for Inventory system design. I adopted a similar system to ShooterGame and how it handles it’s weapons since it’s pretty **** nice actually, and with some modification works really well for me.

Essentially each ‘Weapon’ is an item in the world, it’s an Actor. It doesn’t have to have any scene components (I.e., it’s just an ‘entity’ with no real geometry or transform). You create those Weapons via the ‘SpawnActor’ function and then your ‘Inventory’ just stores a pointer reference to it. In my case, my ‘Inventory’ is literally just an array in another ActorComponent (which allows the Actor to have an inventory of weapons or whatever).

When you ‘Remove’ a weapon from the Inventory, you call ‘OnLeaveInventory()’ on the weapon which performs things like hiding the mesh, setting it’s pointer references to NULL etc, then mark it for delete by calling ‘Destroy()’ on it. It’s fairly easy really. The advantage of storing your ‘Inventory’ items as actors of their own instead of just setting data values in your main inventory class, is that you can call functionality on them that may be unique to that object.

For example, if you have some items that can be ‘Opened’, but a backpack does something differently when it opens to say, a torch, you can just call it from the Inventory manager and the actual object itself will do what it needs to. This way you can keep the system nice and modular without having to add an ***-load of code to your inventory class to handle all different cases.

That’s a really neat way to do things. This is getting into a gray area where game-specific concerns are going to rule, but if workflow between artists and programmers is a big concern for your item system, you should probably also be looking at the possibility of using CSVs/other external data sources to edit and organize your item data, and simply import your CSVs into your game and parse it into a predesigned class.

Yeah eventually somethign like that. I am actually waiting to see what details Epic is going to have about the new mod stuff, as I am trying to design from the ground up for an extremely moddable game. Right now I am just prototyping and figuring things out.

I have written an inventory system at least 3-4 differet ways. If you are going to utilize structs, your struct keeps a reference to the class type to spawn when dropped. You can use UObjects if you want some blueprint interactivity between your UItems and your Inventory system or different behaviors when used, they are easily automatically garbage collected and you can make them Replicatable for network games. Both Struct and UObject bases work fine, but I ended up settling on the AActor because I wanted a 3D preview without spawning a new AItem to view (plus replication is built right in).

By utilizing a UObject or AActor system I too was having an issue dealing with “How will designers interact with this”. What ended up happening Is I utilized a UActorComponent and an array of structs to initialize my characters inventory at begin play and then ditch and destroy the initializer so that it was not taking up any memory. This worked best for me because I was already utilizing UStructs for Saving and Loading Items, so I simply used the same structure I saved and loaded from in my UCharacterInitializer. The REALLY cool thing you can do is override the

void PostEditChangeProperty(struct FPropertyChangedEvent & e) // for single properties

and/or

void PostEditChangeChainProperty(struct FPropertyChangedEvent & e) // for array properties such as arrays of structs

These two functions on my UCharacterInitializer are called automatically within the editor whenever you change a property (including values within a struct and I ensure they only fire in the editor). When the function runs I create an instance of the class set within the struct. Each of my AItems have a method that populates the properties of the struct automatically (hence saving functionality) I simply call that same function from the item instance to populate the struct that exists within the editor (keeping any important values such as the number of items in the stack). This way my struct is fully configured with NO extra work on a designers part besides entering the type of class they want and the number of items they want. I even threw in error checking to ensure the designer could not exceed the maximum stack size of an item which is designated on a Per-Item basis (but defaults to 20). I am also working on doing character customization in this manner so that you can change the apperance of a Character within the editor.

There are other ways to do this, you can build a custom plugin that will do this for you, but for me I did not want to deal with that at the moment, I wanted to build a game. In the future If I do decide to utilize a plugin I can easily ditch the initializer object because it exists in it’s own contained system.

Yep, this is how I handle things too, very neat stuff.

Where do you ended up ‘storing’ it? Is it attached to your player or just laying somewhere in the world?

I don’t like things laying around and invisible, so Each AItem has functions for OnPickedUp() and OnDropped(). OnPickedUp() removes the AItem’s Visibility, turns off it’s collision, Deactivates it’s physics, and attaches it to it’s new owner’s root component. The OnDropped Sets the Actor to Visible, turns on it’s collision, and activates it’s physics.

I have been reading some information on replication and streaming levels that “may” suggest attaching the items to the character is not really a necessary… but I think I’m still going to attach it.

Due to my requirement for replication and the nature of the game there is a bit of a hitch. You’ll notice I did not mention anything about “Detaching” from the owner’s Root component when dropping. That is because when a player picks up or drops an AItem the original AItem is Destroyed and a new item is spawned. I do this to keep owner “clean” for replication because I only want Picked up AItems to replicate to their owner. When dropped I want other players to be able to pick up that item. If you don’t mind other player’s inventory replicating to other clients this is not an issue (such as stealing from players), but I also do it to reduce bandwidth for replication. I haven’t tried it yet but my plan is to send an array of structures if a player wants to steal something from another character or player.

Another thing to note is that for Replication purposes my AItem does NOT have ANY Server functions. Only the owning actor can execute actions such as “use” or “drop” and most of the AItem’s functions are composed with Authority and/or Server checks.

This is really neat… so with your method, is the player inventory just a TList<AItemClass*>? How do you handle serializing the items? With a struct it seems like you could just save the TList<MyStruct>, but making items physical actors in the world seems like it would complicate it.

This might be getting pretty abstract, but do you happen to know how much more memory (if any) storing items in Actor subclasses instead of Structs consumes? That’s the only concern I can see with this method, but I have no idea what the footprint of AActors is like compared to structs.

Technically I keep an array of TArray<AItem*> items. The best thing about Actors is they pretty much self replicate. No need to do anything except put the replicates tag on the array, and Add the array to the DOREPLIFETIME macro. In the constructor of my AItem I simply set them to replicate.

Originally I thought the same thing about the Memory Footprint of an Actor but from everything I have read and seen Unreal Engine is capable of handling a LOT of Actors. I can tell you there is also a LOT more memory required for an AActor compared to a UObject or Struct. In my opinion it depends on what you “need” from your inventory system as these items all have their advantages and disadvantages. If you are just going to display information then use a Struct or UObject. If you are going to give a 3D visual representation of the item in the characters inventory then I suggest an Actor that way you don’t have to spawn the item and then destroy it constantly for display. If you want some higher level of interactivity between your player and inventory items (such as equipping gear or applying specific effects to the character) I suggest UObject or AActor over struct. Generally structs will have the smallest footprint followed by UObject followed by AActor. All 3 can replicate but AActor and Struct replicate the easiest.

One my my earliest implementations of an inventory system I used UObject as my Item Data when it was within my inventory and an ItemActor when it was in the world. The ItemActor contained the UItem object or the players inventory contained the UItem Object. When the player picked up the Item from the world only the UItem was given to the players inventory and the ItemActor was Destroyed. When the item was dropped from the players inventory the UItem spawned an ItemActor into the world and it was set to that ItemActor. This worked pretty well but it requires both the UItem and ItemActor to have a cross reference to each other’s types, which can be a bit cumbersome as a Designer must build both a UItem for Data and an ItemActor for world visual representation.

But as you can see there are MANY different ways to make an inventory system. I personally have never liked using structs because I’ve always had the requirement that each item does something completely different and needs some level of interaction between the owning player and it that can be defined as Item blueprints. So for me UObject or AActor have been my preferences.

True, though it still bothers me when I imagine my character running with 100+ attached actors, which are still replicating even if only to this character.

Substitute UObject for struct and this is pretty much how I have my inventory set up. But in my case, as I’ve said before, designer only creates a 'pickup (an actor) and populate the item data on it. Then, I can just generate the actual item struct at runtime whenever I need it.

Btw, have you managed to use EditInlineNew and Instanced on UObjects? So that it’s possible to create them within the editor? Or did you just subclass them?

It used to bother me as well. For me it was the perception that “Actors” have a position, occupy space, and are ticked but this is not always true. The PlayerController and Any AInfo Object do not really do this; yes they have a position, but they exist only to facilitate some greater functionality. My AItems when attached to the character do not technically move as the attachment sets their relative position to that of the Pawn by default, I have also disabled their ability to Tick (at least when they are in my inventory). But this may not be enough; to save on bandwidth for replication and memory I also utilize an Item stacking system for most items so if you are carrying 20 berries, you are actually only carrying 1 berry Actor with a stack count of 20, so that cuts down the Actor replication Cost. However Weapons and Armor are all “unique” so… no stacking there, but I do also utilize a limited inventory slot system (though it does have an unlimited mode).

I originally was looking to do something like that for the ItemActor with UObjects (To make life easier) but for me my Items have always had a need to be very dynamic, each one doing something completely different and requiring functionality configuration via Blueprints for when the item is used by the player. For instance a Consumable item needs to apply it’s effects, a Weapon or Armor needs to equip to the proper equipment slot and may also apply effects to the player (such as setting enemies who hit them ablaze). Granted you could specify all that functionality in the ItemActor and keep the type of class you need to spawn in order to apply those effects so that when the player “uses” the item you spawn an actor, apply the effects, and then destroy it after it is done. For this method I worry about thrashing memory though, but Epic may have build a more efficient memory allocator with their Garbage Collector. As it is my current method of Spawning an new item for pickup and drop bothers me, but I was told if I want to switch on and off replicating only to owners that is how I needed to do it from an Epic staff member… It did actually end up working faster replication wise in the end… much faster…