Skip to content

Items and Fragments

Items and Item Fragments are one of the most important object types in the Inventory Framework. Let's understand how they work together and possible approaches to create your own items.

Item Definitions

Summary: Items Definitions
  • Item Definitions are created from the NinjaInventoryItemDataAsset.
  • Items are meant to be built via aggregation, but also support inheritance.
  • Every item is backed by an Item Definition and Item Fragments.
  • Item instances share the same instances of their Item Definition and Item Fragments.

Items are defined by Data Assets and instantiated whenever added to an inventory. Every item available starts with its definition, which is done via the Primary Data Asset NinjaInventoryItemDataAsset.

This data asset by itself does not store a lot of information, but it allows you to add Fragments to an item, which are a very powerful and flexible way to configure your items using aggregation, but we will get back to them in a moment.

If for any reason you feel that your items must be modified by inheritance instead of aggregation, then you can also extend the NinjaInventoryItem class and set your specific instance for that item. You can define a class for a specific item, or globally set the item instance in the Inventory Settings page.

Once an item is added to an Inventory Manager, the instance defined by the class is instantiated and stored. The instance can always access its own definition and therefore, its own fragments.

It's important to keep in mind that the Item Definition is a single instance used by every item from that instance. Let's say you have a definition for a sword, and then you have ten characters in the game, each one holding that sword, then you will have ten item instances and just one item definition.

Item Fragments

Summary: Item Fragments
  • The base class for Item Fragments is NinjaInventoryItemFragment.
  • Item Fragments are used to create items via aggregation.
  • They apply the concept of Inversion of Control, modifying items from the outside.
  • Fragments can be stateful, but item data must be stored in item instances, using Memory Structs.
  • The same fragment instance exists for all items created from the same definition.
  • Fragments can interact with each other, via direct calls, interface calls, memory structs and delegates.
  • Fragments can broadcast information, but make sure to do that using the memory replication hooks.

Item Fragments are represented by the NinjaInventoryItemFragment class and are responsible for the "heavy lifting" regarding logic and data managent related to items stored in an Inventory. This approach allows a clear separation of different aspects of an item, such as the Stack management, Container Setup, Equipment, and so on. This design promotes aggregation when creating items in your game.

In their simplest form, they provide an Apply and Revert function, both receiving an Item as a parameter. These functions are automatically invoked when a new item is added or remove from the Inventory Manager, and they can be used to modify an item in any way necessary. Therefore, via inversion of control, Item logic is not mananaged by items themselves, which is a common expectation in OOP. Instead, logic is done externally in multiple Item Fragments assigned to an item, via their Item Definition.

For more elaborate logic and flow controls, Fragments can have their own state, but keep in mind that this state should only ever control the Fragment itself, regardless of any item. For example, you can cache early on another fragment that is constantly accessed by the fragment, to avoid frequent fragment queries. Remember that regardless of how many Items were created from the same definition, they share the same Item Fragment instance!

Since complex logic is meant to be created in these Fragments, it's expected that they would communicate with each other. This can be done via Interface Calls (if your fragment implements a specific interface), Direct Calls if you know exactly which fragment is being used, Delegates exposed by other fragments and so on.

Delegates exposed by fragments require special attention in multiplayer games. You usually would want these delegates to broadcast in all clients, so they usually would need to be replicated when the fragment's memory replicates. For that, fragments will also expose functions aware of the memory state: HandleMemoryCreated, HandleMemoryUpdated and HandleMemoryRemoved. These are automatically invoked and you can use them to detect and broadcast changes via delegates.

Fragment Abstractions

Summary: Fragments Abstractions
  • The Inventory Manager never accesses fragments directly. Only abstractions.
  • Fragments can be abstracted into interfaces and base classes.
  • Familiarize yourself with the abstractions and interfaces if you are creating fragments.
  • Fragments modifying items being added should be ordered appropriately in Item Definitions.

The base fragment class, NinjaInventoryItemFragment is available in the main Inventory module, but all actual fragment implementations are built in the Gameplay module. It was designed this way so all fragments can access functionality from Inventory and Equipment, along with other support Gameplay elements.

However, some elements are fundamental to the Inventory Manager, such as stacks and containers. For situations like that, interfaces were created in the core Inventory Module used to find any viable fragment implementing them.

Even though fragments can be created (or extend) in Blueprints, it's very likely that some of them could perform operations that usually would perform better in C++. Keep that in mind when deciding if you are creating Fragments in Blueprints or C++. Regardless, the system should support you on both.

There are a few different interfaces and abstract classes used by Fragments and by the Inventory Manager. There is a dedicated section on all these foundational elements so make sure to familiarize yourself with them, in particular:

  • The base Fragment class, NinjaInventoryItemFragment.
  • The Fragment used to perform operations on items, ItemFragment_OperableItem and its interface, OperableItemInterface.
  • The Fragment used to apply and remove Gameplay Effects on its avatar, ItemFragment_GameplayEffect.
  • The Interfaces used to validate and modify item contexts, ItemContextValidatorInterface and ItemContextModifierInterface.

Item Instances

Summary: Item Instances
  • The base class for Item Fragments is NinjaInventoryItem.
  • Item Instances are only valid within the scope of an Inventory Manager.
  • They are responsible for storing and replicating data from Item Fragments.
  • Very lightweight and don't contain any logic as those should be in appropriate Fragments.
  • You can create your own item instance for a specific purpose, or globally via settings.

These are representations of items actually stored and managed by an Inventory Manager. An Item can represent a single item istance or a stack depending on its fragment configuration.

The responsibility of an Item Instance is to provide access to all Item Fragments operating on it and managing all their memories. You can obviously add more to them if you need, and in some occasions that could be a good idea. The best reason why you could want to extend an Item Instance is to simplify Fragment Memory setup, replacing the Fragment Structs by actual attributes in your Item class. But this is a performance adjustment only to be considered for a large amout of items that must be maintained in the game.

Since the bulk of the logic that belongs to items lives outside the instance, in the Item Fragments to be more specific, Items are quite lightweight, which is desirable since you could have a lot of item instances in your game, without the memory cost of larger entities.

You can also create specific Item Instances for specific items. Maybe items with a lot of attributes or some specific logic that fits in their core definition. Or you can also create a base global item that can be assigned to all Item Definitions, via the Inventory Settings page.