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"

What is the best way to handle Saving/Loading an Array of Objects?

I've looked at tutorials, Tappy Chicken and Rama's example, but can someone tell me what is the "recommended" way to save and load an array of objects?

More specifically, procedurally generated actors, which seem to break the FArchive derived routines in the engine (they use FindObject, but since they are procedurally generated, they are not assets). I can code up something custom, but I was wondering if I missed something built-in that would do the transforms, materials, etc.

Product Version: Not Selected
Tags:
more ▼

asked Apr 27 '14 at 03:23 AM in C++ Programming

avatar image

Andargor
122 16 18 20

(comments are locked)
10|2000 characters needed characters left

3 answers: sort voted first

There is currently no good tutorial on how to do a custom save game setup for your game, so it will require a good bit of custom coding on your part. But here's some info that may help out:

For fortnite, we're using a system built on the SaveGame property flag. If you set the ArIsSaveGame archive flag on an archiver, it will only serialize properties that have that flag set on them. Some of the basic properties are set this way in the engine, and you can then tag your game specific properties.

So, you need to set up a savegame archive. For fortnite, we're using a proxy wrapper based on the Objects-as-strings proxy wrapper:

 struct FFortniteSaveGameArchive : public FObjectAndNameAsStringProxyArchive
 {
     FFortniteSaveGameArchive(FArchive& InInnerArchive)
         :   FObjectAndNameAsStringProxyArchive(InInnerArchive)
     { 
         ArIsSaveGame = true;
     }
 };

 

Then, you can use that proxy archive to serialize a record for an actor or object you wish to. Here's our save code, that writes to a simple struct that has the actor's class, transform, and a TArray storing the bytestream:

 ActorRecord->ActorClass = Actor->GetClass();
 ActorRecord->ActorTransform = Actor->GetTransform();
 ActorRecord->ActorName = Actor->GetName();
  
 FMemoryWriter MemoryWriter(ActorRecord->ActorData, true);
  
 // use a wrapper archive that converts FNames and UObject*'s to strings that can be read back in
 FFortniteSaveGameArchive Ar(MemoryWriter);
  
 // serialize the object
 Actor->Serialize(Ar);

 

And here's our code that restores that actor:

 FActorSpawnParameters SpawnParameters;
 SpawnParameters.Name = ActorRecord->ActorName;
 AFooActor *NewActor = GetWorld()->SpawnActor<AFooActor>(ActorRecord->ActorClass, TempVector, TempRotator, SpawnParameters);
  
 FMemoryReader MemoryReader(ActorRecord->ActorData, true);
 FFortniteSaveGameArchive Ar(MemoryReader);
 NewActor->Serialize(Ar);

 

So we're using this system for Fortnite, which has a complicated system of procedural generation. Basically there's a state machine that handles either generating the actors randonly, or restoring from a record like above. We also use a similar technique to save a player's inventory, but instead of saving a whole actor we just serialize a specific Struct, which is a great place to put your array of objects:

 FMemoryWriter MemoryWriter(PlayerRecord->BackpackData, true);
 FFortniteSaveGameArchive Ar(MemoryWriter);
 Inventory->Serialize(Ar);


more ▼

answered Jul 01 '14 at 01:06 AM

avatar image

[Epic]Ben Zeigler STAFF
1.3k 29 131 75

avatar image Tarostar Nov 16 '14 at 01:22 PM

I've been searching everywhere, reading and re-reading the documentation to figure out how to most easily serialize all actors when saving and then spawning them again when loading. This is the best answer, but still only shows part of the solution and the only way I've managed to get save/load working is using Rama's code as a starting point and then writing a SaveLoad function for every class which then handle spawning actors when loading. This is a lot of work and very error prone, so I would LOVE to see a working example of saving a bunch of actors.

I understand that ActorRecord is a struct, but is ActorData:

 TArray< uint8 >  ActorData?

When you call Actor->Serialize(Ar); does that write to this ActorData?

Then on load you use the ActorRecord to create the SpawnParameters, but I'm not sure how the ActorRecord is itself loaded?

A small, but complete save/load example serializing objects would really help me get going.

avatar image marsonmao Jun 16 '16 at 04:02 AM

Yes, ActorData is TArray. And you can save the ActorRecord in a save game object.

avatar image AssemblerJohn Mar 19 '18 at 06:49 AM

I'd still have a question if possible. For example if a character is in middle air swinging his weapons around will that be serialized too?

For my example I have an RPG, however at the moment I'm using an workaround so that when the player is in combat a save is not possible, because I don't know how to serialize the animation state.

My question is, if I'm using something like yours, can I also serialize the state of animated objects? That is is a character is right in the middle of an attack will that be serialized/saved? That requirement is quite standard for all games, however I'm not sure it's easily do-able in Unreal?

Thanks & regards!

(comments are locked)
10|2000 characters needed characters left

The << Operator

"something built-in that would do the transforms, materials, etc."

Check out ArchiveBase and Archive.h

If you have a UE4 type, try using the << operator on it!

Transforms, Materials, Etc should all be covered by the << operator already.

Then for your class you define your own use of the << operator, which uses the existing UE4 type << usage

Here's an example:

 //JSMA
 USTRUCT()
 struct FRedStruct
 {
     GENERATED_USTRUCT_BODY()
 
     //Vars
     UPROPERTY()
     int32                     VictoryVibe;
     
     UPROPERTY()
     FTransform             VictoryTransform;
     
     UPROPERTY()
     FName                 MeshPath;
 
     UPROPERTY()
     bool StartsDisabled;
     
     //default properties
     FRedStruct()
     {
         VictoryVibe = 0;    
         MeshPath = FName(TEXT(""));
         StartsDisabled = false;
     }
 };
 
 
                                         //could use a class instead of struct
 FORCEINLINE FArchive &operator <<(FArchive &Ar, FRedStruct& TheStruct )
 {
     Ar << TheStruct.VictoryVibe;
     Ar << TheStruct.VictoryTransform;
     Ar << TheStruct.MeshPath;
     Ar << TheStruct.StartsDisabled;
         
     return Ar;
 }

Spawn and Load

Final step when loading is to spawn fresh copy of class and then use the << operator on it! (or fresh struct)

Enjoy!

:)

Rama

more ▼

answered Apr 27 '14 at 05:00 AM

avatar image

Rama
10.6k 445 343 1083

avatar image Andargor Apr 27 '14 at 02:20 PM

Thanks Rama, I know about that operator. What I am looking for is the proper way to handle procedural objects. I had looked at the header files, and saw that everything derived from FMemoryArchive has the << operator disabled for objects. And the ones for UObject (in ArchiveUObject.h) require assets, for which there are none in procedural generated objects.

avatar image Rama Apr 28 '14 at 03:38 AM

I have an entire in-game editor where I load and save characters, destructible meshes, static mesh actors, materials, material instances, and much more!

The process is pretty simple

  1. Saving: save the core data that you need that is unique to that actor / object

  2. Loading: load a fresh instance of the actor / object, and then reapply the core data you saved to hard disk.

For procedural mesh

save the triangle data to hard disk, and also the transform and material path

when loading, load a newly spawned procedural mesh with no data, then load in the triangle data from hard disk

it's not hard :)

I've already set the whole thing up for my own use of procedural meshes, thanks for doing all that research on this topic!

Dynamic Load Object

to load materials you can use my wiki on the subject

https://wiki.unrealengine.com/Dynamic_Load_Object

Rama

avatar image Andargor Apr 28 '14 at 03:46 AM

Thanks again Rama, but it is not the answer I am looking for. I too have a save system that works the way you describe, but there is a whole object archiving infrastructure included in the engine. I want to know what the recommended way of using it is, instead of doing low-level archiving.

avatar image Rama Apr 28 '14 at 03:48 AM

Unresolved

hmm okay, good luck with that, you will always save space by doing more low-level though :)

file sizes in my project are positively tiny as a result :)

Rama

avatar image JoshHotGlueGames Mar 23 '16 at 05:04 PM

Hey Rama,

I’ve been following your Custom Save to Binary Files post on the wiki the past couple days: https://goo.gl/KuhndN

I’m having trouble figuring out how to dynamically save a whole set of objects at runtime based on the ‘SaveGame’ bool that’s a UPROPERTY specifier (or found within a blueprint variable). As it looks right now, it seems like your method needs to explicitly state what kinds of variables will be loaded into the function (unless I’m missing something).

I’ve implemented your approach into a base class inheriting from Actor, so that I can drag it into the scene in order for my UI blueprints to call it. I’ve created Save, Load and SaveLoad functions just like the ones you provided, as well as an additional function that gets called from blueprint (since it didn’t like accepting a SaveBuffer as an input for a UFUNCTION). Currently I’d like to just grab the player controller’s location to save and load it. I can do this in a more convoluted way by passing in the actor through blueprints, grabbing it’s world location in code and storing that vector into the save and load functions. Doing this for every individual variable is highly unperformative, as you could imagine.

How can I pass variables into these functions with explicitly stating all of their types? Is there a way to store all UPROPERTIES under the ‘SaveGame’ specifier into some sort of array that’s passed into this class?

Currently I’m looking into this solution:

https://answers.unrealengine.com/questions/42349/how-do-i-use-the-savegame-flag.html

The issue is that I don’t understand how to combine your binary method with these other methods of using LoadSaveFromSlot, etc. I’d love to continue using binary conversion because it seems like a much cleaner way to store and load variables.

I apologize if this reply doesn't really have to do with the original post, but these forums contain no way to private message users from what I can tell

(comments are locked)
10|2000 characters needed characters left

Hi Guys, I was struggling with this for a bit and still learning best way to do it. I've create a wiki page showing what i've setup so far if it might help with your setup in anyway, posting here because this is one of the most complete answers and most helpful for me so just thought I could add to it if it helps anyone else:

https://wiki.unrealengine.com/SaveGame_Pointers_and_Structs

Feel free to offer any suggestions to update the page or clarify anything if you want :)

more ▼

answered Oct 19 '17 at 11:09 AM

avatar image

Fishy418
43 6 6 8

(comments are locked)
10|2000 characters needed characters left
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