Data Mixin System

Generic Inventory System (GIS) plugin is a flexible tool for Unreal Engine (UE5). It enables dynamic runtime data attachment via Data Mixin System, supporting serialization & network replication. Ideal for dynamic state management like quest systems, helping game devs manage custom data efficiently.

通用库存系统.封面
罗传月武(YueWu)

Author

罗传月武(YueWu)

专注游戏开发和Web技术。

Created: Jul 19, 2025Updated: Sep 15, 2026

Table of contents

Overview

The Generic Inventory System (GIS) offers a flexible mechanism called the Data Mixin System, enabling dynamic runtime data attachment (via FInstancedStruct) to any object (e.g., UObject) with support for serialization (with limitations) and network replication. This design is ideal for extending dynamic data to target objects without modifying their original structure.

For C++ User only

This article is intended only for C++ users who wish to develop other game systems using this system; Blueprint users need not read this article.

Use Cases

The Data Mixin System is suited for scenarios requiring dynamic state management. For example, in a Quest system using different DataAsset objects to define each Task (e.g., objectives, descriptions, rewards), the system can be integrated to allow each task type to manage its internal state with custom data structures.

Example

For a task requiring “killing 5 bandits and 3 wolves,” you can define a struct TaskState_KillEnemy with fields BanditKilled and WolfKilled to track the task’s progress.

Data Mixin Container

GIS provides data mixin functionality through GIS_MixinContainer, which maintains an Object->InstancedStruct key-value pair array. Implemented with FastArraySerializer, it supports efficient network replication and simplified data change notification callbacks.

Steps to Use the Data Mixin Container

Using ItemInstance as an example:

1.Add a GIS_MixinContainer field to your class.

cpp
1 /**
2 * Container for each fragment's runtime state.
3 * 每个片段运行时状态的容器。
4 */
5 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category="ItemInstance", meta=(DisplayName="Fragment States", ShowOnlyInnerProperties))
6 FGIS_MixinContainer FragmentStates;

2.In the constructor, set the container’s OwningObject to the current object (for ActorComponent, set it in InitializeComponent).

cpp
1UGIS_ItemInstance::UGIS_ItemInstance(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer), FragmentStates(this)

3.Ensure the field supports network replication, with synchronization conditions customized to project needs.

cpp
1void UGIS_ItemInstance::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
2{
3 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
4 // FastArray don't need push model.
5 DOREPLIFETIME(ThisClass, FragmentStates);

4.Implement the IGIS_MixinOwnerInterface interface in your class to respond to data changes via its functions.

cpp
1class GENERICINVENTORYSYSTEM_API UGIS_ItemInstance : public UObject, public IGIS_MixinOwnerInterface
cpp
1 /**
2 * Called when mixin data is added to the owning object.
3 * 当混合数据被添加到拥有对象时调用。
4 * @param Target The target object to which the data is attached. 数据附加到的对象。
5 * @param Data The added instanced struct data. 添加的实例化结构数据。
6 */
7 virtual void OnMixinDataAdded(const TObjectPtr<const UObject>& Target, const FInstancedStruct& Data) = 0;
8
9 /**
10 * Called when mixin data is updated in the owning object.
11 * 当拥有对象中的混合数据被更新时调用。
12 * @param Target The target object to which the data is attached. 数据附加到的对象。
13 * @param Data The updated instanced struct data. 更新的实例化结构数据。
14 */
15 virtual void OnMixinDataUpdated(const TObjectPtr<const UObject>& Target, const FInstancedStruct& Data) = 0;
16
17 /**
18 * Called when mixin data is removed from the owning object.
19 * 当从拥有对象中移除混合数据时调用。
20 * @param Target The target object to which the data was attached. 数据附加到的对象。
21 * @param Data The removed instanced struct data. 移除的实例化结构数据。
22 */
23 virtual void OnMixinDataRemoved(const TObjectPtr<const UObject>& Target, const FInstancedStruct& Data) = 0;

5.The target object (e.g., Item_Fragment) must implement the IGIS_MixinTargetInterface interface to define runtime data types, default values, and serialization requirements.

cpp
1class GENERICINVENTORYSYSTEM_API UGIS_ItemFragment : public UObject, public IGIS_MixinTargetInterface
cpp
1 /**
2 * Determines if the mixin data can be serialized.
3 * 确定混合数据是否可以序列化。
4 * @return True if the data is serializable, false otherwise. 如果数据可序列化则返回true,否则返回false。
5 */
6 virtual bool IsMixinDataSerializable() const = 0;
7
8 /**
9 * Retrieves the compatible data structure for the mixin.
10 * 获取混合数据的兼容数据结构。
11 * @return The script struct compatible with the mixin data. 与混合数据兼容的脚本结构。
12 */
13 virtual TObjectPtr<const UScriptStruct> GetCompatibleMixinDataType() const = 0;
14
15 /**
16 * Generate default runtime data for compatible data type.
17 * 生成兼容的混合数据类型的默认值。
18 * @param DefaultState The default value of compatible data. 兼容的数据结构默认值。
19 * @return If has default value. 是否具备默认值?
20 */
21 virtual bool MakeDefaultMixinData(FInstancedStruct& DefaultState) const = 0;

API

The GIS_MixinContainer provides APIs for adding, removing, saving, and loading data. Refer to the project source code for detailed usage.

Usage Limitations

While the Data Mixin Container supports attaching runtime state to any object, for save support, note:

  • The target object (TargetObject) must be loaded from a Package (e.g., a DataAsset).
  • Custom structs must support the SaveGame property, and their field types must be serializable by Unreal Engine.

示例

An example of custom runtime state (notes the tooltip):

道具实例.数据混入系统