Custom structure serialization in Unreal Engine

WILD

Administrator
Staff member
ADMIN
SELLER
SUPREME
MEMBER
Joined
Jan 21, 2025
Messages
220
Reaction score
629
Deposit
0$
Допустим, вы создали собственную USTRUCT на C++ и теперь хотите её сериализовать.

USTRUCT(BlueprintType)
структура FComplexStruct
{
GENERATED_BODY()

UPROPERTY(EditAnywhere, BlueprintReadWrite)
FNonSerializableStruct FirstStruct;

UPROPERTY(EditAnywhere, BlueprintReadWrite)
FSerializableStruct SecondStruct;
};


Обычно достаточно просто отметить нужные поля с помощью функции SaveGame.

USTRUCT(BlueprintType)
структура FComplexStruct
{
GENERATED_BODY()

// Не поддерживает сериализацию
UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame)
FNonSerializableStruct FirstStruct;

// Поддерживает сериализацию
UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame)
FSerializableStruct SecondStruct;
};


Но вот в чем проблема — для того, чтобы это работало, сами поля должны поддерживать сериализацию.
К сожалению, одна из наших переменных этого не делает.

В моем случае это структура под названием FNonSerializableStruct. Из-за этого сериализуется только вторая структура, хотя мы пометили обе с помощью SaveGame.


Решение​

Что же нам делать в этом случае?
Нам придётся вручную сериализовать нашу структуру.

К счастью, это довольно просто.
Для этого нам нужно добавить следующий код вне структуры, в глобальную область видимости файла:

inline FArchive& operator<<(FArchive& Ar, FComplexStruct& Save)
{
Save.Serialize(Ar);
вернуть Ar;
}

шаблон <>
struct TStructOpsTypeTraits<FComplexStruct> : public TStructOpsTypeTraitsBase2<FComplexStruct>
{
перечисление
{
WithSerializer = true
};
};


Здесь, в шаблонной структуре, мы сообщаем движку, что хотим вручную обрабатывать сериализацию для нашей структуры.

Перегрузка оператора << добавлена просто для удобства — чтобы нам не приходилось вызывать метод Serialize вручную каждый раз, когда мы используем эту структуру в качестве члена в другой структуре или классе.

Итак, что дальше?
Мы еще не написали логику сериализации.

Как я уже упоминал ранее, нам нужно будет добавить метод Serialize к нашей структуре.
Unreal будет вызывать его автоматически при необходимости — благодаря коду, который мы добавили выше.

bool Serialize(FArchive& Ar)
{
// Сериализация партиями, поскольку поддержка отсутствует.
Ar << FirstStruct.Type;
Ar << FirstStruct.Class;
Ar << FirstStruct.Object;

// Сериализуйте весь код целиком, поскольку такая возможность поддерживается.
Ar << SecondStruct;

вернуть true;
}



Улучшение​

Вы, вероятно, заметите, что код для добавления поддержки сериализации довольно шаблонный. И вы знаете, что это значит — мы можем обернуть его в макрос, чтобы значительно упростить добавление поддержки других структур!

#define MAKE_SERIALIZABLE_STRUCT(Name) \
inline FArchive& operator<<(FArchive& Ar, Name& Save) \
{ \
Save.Serialize(Ar);
return Ar;
} \
шаблон<> \
struct TStructOpsTypeTraits<Name> : public TStructOpsTypeTraitsBase2<Name> \
{ \
перечисление \
{ \
WithSerializer = true, \
}; \
};


Теперь мы можем просто включить наш макрос в заголовочный файл и добавить поддержку сериализации для любой из наших структур чистым и лаконичным способом.
 
Top Bottom