x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Blueprint structure can't be correctly saved (serialized)

I'm using the Archive class to implement a save game system. My goal is to serialize any actor and its variables which enable the SaveGame property flag.

So I made an Archive inherits FObjectAndNameAsStringProxyArchive and set ArIsSaveGame to true, and I can enable the SaveGame of any varialbe and they are serialized.

But I found that this works inappropriate for the variables of Blueprint structure type. Even if I check the SaveGame for it, the members are not serialized.

My codes are like below:

 struct FVRSaveGameArchive : public FObjectAndNameAsStringProxyArchive
 {
     FMySaveGameArchive(FArchive& InInnerArchive)
         : FObjectAndNameAsStringProxyArchive(InInnerArchive, true)
     {
         ArIsSaveGame = true;
     }
 };

 FMemoryWriter MemoryWriter(record.data, true);
 FMySaveGameArchive Ar(MemoryWriter);
 actor->Serialize(Ar);

In this way all primitive type (integer, float...etc.) variables are saved correctly, but Blueprint structure type variables are not.

Product Version: UE 4.12
Tags:
more ▼

asked Jul 15 '16 at 06:47 AM in C++ Programming

avatar image

marsonmao
230 8 18 25

avatar image marsonmao Jul 15 '16 at 06:49 AM

Actually I found that the problem is here:

 bool UProperty::ShouldSerializeValue( FArchive& Ar ) const
 {
     if (Ar.ShouldSkipProperty(this))
         return false;
 
     if (Ar.IsSaveGame() && !(PropertyFlags & CPF_SaveGame))
         return false;
 
     static uint64 SkipFlags = CPF_Transient | CPF_DuplicateTransient | CPF_NonPIEDuplicateTransient | CPF_NonTransactional | CPF_Deprecated | CPF_DevelopmentAssets;
     if (!(PropertyFlags & SkipFlags))
         return true;

If my archive is Ar.IsSaveGame() == true, then the propery must be CPF_SaveGame enabled, however the Blueprint structure properties are not enabled, so they can't be saved. So I think UE should provide the way to enable CPF_SaveGame for BP structure properties.

avatar image marsonmao Jul 22 '16 at 08:33 AM

Bump! Would like to know if Is this is intended/future work/won't fix/real bug, thanks!

avatar image ImVawx ♦♦ STAFF Jul 22 '16 at 01:07 PM
avatar image marsonmao Jul 28 '16 at 06:47 AM

Hi Kyle: Thanks for the link, I've already know that, and my question is about to serialize a Blueprint struct, not CPP struct. The question is how to serialize a Blueprint struct when Archive is set to ArIsSaveGame == true.

avatar image BrUnO XaVIeR Aug 30 '16 at 03:25 PM

I have the same problem :)

avatar image BrUnO XaVIeR Apr 22 '18 at 10:51 AM

Coming back to this problem again this month; For my projects I solved this issue by completely discarding use of FArchive classes and avoiding the Serialize() methods.

I've created my own serializer based on UProperty reflection + JSON to replace the ProxyArchive class. Now I can finally read/write to structs created as Blueprint assets (user defined structs).

avatar image Flashback Jun 25 '19 at 01:00 PM

Still not fixed in 2019, unfortunately :(

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

Same problem and we may need a issue number to track this

more ▼

answered Sep 24 '16 at 11:24 PM

avatar image

skeleton60
625 42 60 88

avatar image ImVawx ♦♦ STAFF Sep 26 '16 at 01:01 PM

If you are having an issue where the answer here isn't related, please make a new post in Bug Reports and give detailed steps on how to reproduce it. Here is a guideline on how to write up an issue:

https://answers.unrealengine.com/questions/12363/how-do-i-report-a-bug.html

Thanks.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Hey marsonmoa,

When it comes to saving Blueprint structs, I suggest following along with: https://docs.unrealengine.com/latest/INT/Gameplay/SaveGame/Blueprints/

Here are some screenshots of what I did:

[Save Struct]

alt text

[Load Struct]

alt text

And then, Print out for the Save Struct:

alt text

Finally, the Print out for loading what was saved:

alt text

If you are still having issues, update your post with what your problem is.

  • Follow up

This works the same way in C++

CSaveGame.h

 #pragma once
 
 #include "GameFramework/SaveGame.h"
 #include "CSaveGame.generated.h"
 
 // Structure that is exposed to BP
 USTRUCT(BlueprintType)
 struct FTestStruct
 {
     GENERATED_USTRUCT_BODY();
 
     UPROPERTY(BlueprintReadWrite)
     bool BoolVar;
     UPROPERTY(BlueprintReadWrite)
     int IntVar;
     UPROPERTY(BlueprintReadWrite)
     float FloatVar;
     UPROPERTY(BlueprintReadWrite)
     uint8 ByteVar;
     UPROPERTY(BlueprintReadWrite)
     FVector VectorVar;
     UPROPERTY(BlueprintReadWrite)
     FRotator RotatorVar;
     UPROPERTY(BlueprintReadWrite)
     FTransform TransformVar;
     UPROPERTY(BlueprintReadWrite)
     FString StringVar;
 };
 
 UCLASS()
 class AH452892_API UCSaveGame : public USaveGame
 {
     GENERATED_BODY()
     
 public:
     UCSaveGame( );
 
     // ID for save game
     int UserId;
 
     // Slot name for save game
     FString SaveSlotName;
     
     // Data to save
     FTestStruct SavedTestStruct;    
 };

CSaveGame.cpp

 #include "AH452892.h"
 #include "CSaveGame.h"
 
 UCSaveGame::UCSaveGame( )
 {
     // These can change and probably should with more complex games
     UserId = 1;
     SaveSlotName = FString( "UCSaveGame" );
 }

SerializeActor.h

 #pragma once
 
 #include "GameFramework/Actor.h"
 
 // Need CSaveGame for FtestStruct
 #include "CSaveGame.h"
 
 #include "SerializeActor.generated.h"
 
 UCLASS()
 class AH452892_API ASerializeActor : public AActor
 {
     GENERATED_BODY()
     
 public:    
     ASerializeActor();
 
     virtual void BeginPlay() override;
 
     // Local TestStruct data
     UPROPERTY(BlueprintReadWrite, SaveGame)
     FTestStruct TestStruct;
 
     // Save data to SaveGameObject
     UFUNCTION( BlueprintCallable, Category = "Save|Save Test Struct" )
     bool SaveTestStruct( FTestStruct In );
 
     // Load data from SaveGameObject
     UFUNCTION( BlueprintCallable, Category = "Save|Load Saved Test Struct" )
     FTestStruct LoadTestStruct( );
     
 private:
     // Save game object
     USaveGame *SaveGameObject;
 };

SerializeActor.cpp

 #include "AH452892.h"
 #include "SerializeActor.h"
 
 ASerializeActor::ASerializeActor()
 {
     // No need for this to tick
     PrimaryActorTick.bCanEverTick = false;
 }
 
 // On load
 void ASerializeActor::BeginPlay()
 {
     Super::BeginPlay();
     
     // Create SaveGameObject
     SaveGameObject = UGameplayStatics::CreateSaveGameObject( UCSaveGame::StaticClass( ) );
 }
 
 // Save test struct to our SaveGame
 bool ASerializeActor::SaveTestStruct( FTestStruct In )
 {
     if( SaveGameObject )
     {
         UCSaveGame *RealSaveGame = Cast<UCSaveGame>( SaveGameObject );
         if( RealSaveGame )
         {
             RealSaveGame->SavedTestStruct = In;
             return UGameplayStatics::SaveGameToSlot( RealSaveGame, RealSaveGame->SaveSlotName, RealSaveGame->UserId );
         }
     }
     return false;
 }
 
 // Load test struct from our SaveGame
 FTestStruct ASerializeActor::LoadTestStruct( )
 {
     if( SaveGameObject )
     {
         UCSaveGame *RealSaveGame = Cast<UCSaveGame>(SaveGameObject);
         if( RealSaveGame )
         {
             TestStruct = RealSaveGame->SavedTestStruct;
         }
     }
 
     return TestStruct;
 }

After creating a child Blueprint class of SerializeActor, this is the Blueprint to save and load the Struct:

alt text

more ▼

answered Jul 29 '16 at 03:06 PM

avatar image

ImVawx ♦♦ STAFF
6.8k 114 18 128

avatar image marsonmao Aug 01 '16 at 07:22 AM

Hi Kyle: Thanks for the very detailed answer, I really appreciate it. But please note one very important point, I am using my custom FArchive to do the serialization, which is different with the default one used by UGameplayStatics's functions. My custom FArchive has set Ar.IsSaveGame to true, which leads to another way of the execution, so in that way the BP struct can't be saved properly.

avatar image marsonmao Aug 01 '16 at 07:27 AM

Please check this link link text, the 14 upvoted answer. My custom FArchive is like the FFortniteSaveGameArchive example, and with it I can't save BP struct.

avatar image luca.ferrara Aug 02 '16 at 04:00 PM

Hi, I've exactly the same problem. The issue seems to be that the SaveGame flag is not inherited from struct members.

I hope that behavior will be fixed in the future but in the meanwhile instead of structs I'm using classes that inherits from Object and containing only public members. That works fine and moreover it's possible to set save / transient flags on each 'class' member.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question