Fragments
Last updated
Last updated
Fragments are instance editable structs, which can be dynamically added, removed and modified on containers and items. This allows you to remove data from items and containers that wouldn't need said data in the base struct, giving you a chance of optimizing the memory footprint of your game and giving you a platform to add any data you want to both containers and items.
This data has native serialization support, so it supports all save systems.
Unfortunately, instanced structs can only be made through C++
The plugin has several examples of handling fragment code. The biggest highlights are the template functions provided by the FL_IFP_FragmentHelpers library.
For simple examples, I suggest looking at Internal_AddTagToItem and StartComponent or the Add/Remove/Override functions inside the fragment manager. The majority of the time, you are just using the FindFragment template function to get a pointer to a fragment to modify it.
Fragments follow a specific inheritance setup to allow both containers and items to share certain fragments to reduce duplicate fragments that achieve the same thing.
Both the container and item use FCoreFragment
, but you should most of the time assume the struct is FContainerFragment
or FItemFragment
, depending on which struct you are working with.
The reason why they use FCoreFragment
is to allow both to use fragments that apply to both structs, such as the tag fragment.
In a future update, I will be trying to customize the dropdown menu to exclude fragments based on certain settings. For example, excluding the Random Item Count fragment from the dropdown if the item doesn't support stacking. That customization plans on using the virtual functions found on
FCoreFragment
to handle that.
Due to instanced structs being so young in the engine, I did not feel comfortable putting all the logic around it in the main inventory component. That's why the AC_FragmentManager was made, who will handle everything related to fragments.
The AC_FragmentManager is automatically added to the actor for you if it's missing. But if you want to subclass the fragment manager, you can manually add the component to your actor and it'll be used. Alternatively, you can assign a fragment manager class inside the inventory component class defaults.
The inventory component has a GetFragmentManager function, which hosts all non-static functions related to fragments.
Since fragments are only accessible to C++, this is my workflow for enabling as much C++ and Blueprint support:
Parent your fragment to FCoreFragment
if you want it to be shared between both containers and items. Otherwise, you specify which parent you want.
Every time you make a fragment, you make a new class and put a function library inside of it to give helper functions to Blueprint programmers. This class's prefix should be IF_
(Item fragment) or CF_
(Container Fragment). If it's a global fragment, like the tag fragment, it's just F_
Always create getter functions. If you are working in single player, I'd recommend making setter functions to simplify your work flow.
I will not be supporting multiple instances of the same fragment within the same array. Rather, you should have a fragment contain an array of whatever data you want to have multiple copies of.
IsCompatibleWithContainer - Determines if the fragment is compatible with the container it's being placed in.
IsCompatibleWithItem - Determines if the fragment is compatible with the item it's being placed in.
SupportsItemAsset - Is the fragment allowed in the item asset? Keep in mind, all code utilizing this fragment should not assume the fragment can be in either the item struct or item asset and should not have its data modified while in the item asset.
ShouldRemoveFragment - Whenever a fragment is modified, this function will check if the fragment should be removed. For example, if the fragment has no data inside of it or is no longer being used.
MergeWithFragment - Handles how two fragments are merged.
GetNetworkingMethod - How should the fragment be replicated?
Fragments use the same networking method as the rest of the inventory. They do not use traditional replication, but rather has RPC's forward all modifications to relevant clients.
The fragment manager has six functions for adding, removing and overriding fragments for both containers and items.
Fragments are pure data structs that can be added to the container, item struct and/or item asset, where as traits are data-objects limited to just the item asset.
The main difference is the simplicity of creating traits and working with them.
Fragments are more complicated and Blueprint support is limited, where as traits have full blueprint support and are simpler to work with. Traits main limitation is not changing their variables during runtime, since every item sharing one item asset will have that change reflected for all of them. But that also means that their memory usage is highly efficient. Remember, a unique trait instance is not created per item struct, it's created per item asset. Meanwhile fragments are created per item struct, allowing them to be changed during runtime. (This is assuming the fragment in question is not a fragment in the ItemAssetFragments array, as that array also shares the same limitation of not being mutable during runtime but also being memory efficient.)
I generally use traits for everything that are only related to the item asset and is static data that does not change during runtime.
Constructing a fragment is virtually free. So it just comes down to what you do with the fragment that can cause performance issues, for example; hard referencing assets.