Serializing AbilitySystemComponent data into a saved game [GAS]

I’m working[1] on building a save game system and have run into the difficulty of determining what exactly needs to be saved from the AbilitySystemComponent.

Ideally, I’d save just enough data to restore the game to the precise state it was in when the player saved the game. There are a lot of moving parts in the AbilitySystemComponent though, and I’m not entirely sure what the most minimal set of data would be.

My current list is:

  • The base values of all the Gameplay Attributes that the ASC initially possesses that differ from their initial value.
  • Any attribute sets that were granted that the ASC did not initially possess – the base value for each, if it differs from the default.
  • All Gameplay Effects that are currently active. I think each of these need to include the effect instance or class, the level, any granted tags, and any set-by-caller magnitudes.
  • All granted Gameplay Abilities that were not granted by a Gameplay Effect. I think each of these need to include the ability instance or class, the source object (as a reference), the input datal, any dynamic tags, and any set-by-caller magnitudes.
  • Loose Gameplay Tags, if any

I’m not at all confident that that’s everything, nor that I haven’t included something unnecessary. In particular, it seems like the above list won’t take into account the possibility that some abilities are currently ongoing.

This seems like something that others surely must have figured out before. Does anyone else have their own list of what must be saved?

I’m explicitly excluding granted abilities that were granted by an effect, because the effect will automatically re-grant them. But I’m not completely sure that this is always right – if the ability is instanced, I might need to save it anyway and somehow relink it to its granting effect on load?

I’m also a little unsure about serializing the base values of the attribute sets, as I’m pretty sure I remember that Gameplay Effects can modify the base value… so it could become very messy trying to figure out the base state that everything else is going to build on.


  1. I think it mostly doesn’t matter for this question, but just for the record, I’m currently working in UE 5.0. ↩︎

I’m not claiming to have the best answer possible, but to my understanding trying to save ASC directly is a pure madness.

I had a similar problem (albeit a bit easier and with a power to limit game design where it is inconvenient), and may be my approach will lead you to some adequate solution.
The general idea of solution was: not to save ASC itself, but to save a bunch of top level data that defines the complete ASC state.

For example, my characters has a kinda “actions queue component”, where each action is an object itself. You may consider this actions as a variation of GA, where only one ongoing action is permited.

My save process for actor was:
Save actor => save all saveable components => actions queue component in particular was saving only current action.
The current action has a custom Save and Load functions defined, where action itself defines what to save into passed in save object\structure.
And on practice, 90% of my abilities could been described by:

  • Inputs: target point\unit\etc, a small finite set of data that would let ability to be repeated in exactly the same way if it launched again
  • Phase: literally a enum. Most of my abiltities had a similar phase structure like “initialized => move to target => play montage => end”. Most abiltiies had about 4 phases, a few had up to 7, which are stored in the same single enum.

And that’s it: this is enough to replicate the saved state.

Loading goes as:
Load actor => load all saveable components => action queue component.
Action queue component in its turn checks if save for this unit has an abilitiy data. If so: start this ability with stored Inputs and Phase.
Ability on its start also has a special handler that depending on passed in Phase jumps to corresponding phase of ability. In some cases you would need to instantly apply effects of skipped phases.

This was on load you have a unit with active ability in a state that corresponds to state it was saved in.

I should note that my abilities are a custom UObjects, that sometimes do start a child GAs and sometimes don’t

That’s was a part about saving GAs.

For GEs… you probably can try store data about GE directly from ASC: the class, the inputs, the remaining duration.
In my case i had a custom GE-like system that is more save-friendly, but it may be just not applicable to your\general case.

Tags - those are defined by GEs, so should be solved automatically.
LooseTags - i still wonder why would you ever want to use them in first place. But surely it’s just an FGameplayTagsContainer, so you may easily save\load it.

Attributes saving depends on your game structure.
In my case i have a “map” <FString PresetName, FDefaultAttributesForPreset>. This way i may just save a single string to store all the base attributes and the rest could be adjusted by loaded GEs.

Hope this will give you some ideas on how to proceed. Goodluck

Yes, this is the crux of the question – identifying all the top level data that defines the complete state.

Sorry if I gave the impression that I was trying to directly serialize the ASC. That’s not what I’m doing. I’m copying data from the ASC into a custom struct which I then serialize. Currently I’ve only implemented save and not load, but the idea will be that I deserialize that struct and then copy the data back into the ASC.

Okay, so the implication of this would be that I do, in fact, need to serialize data from any abilities that are currently active, right? The inputs and, if applicable, the phase. Besides target, do you have any other examples of what might count as an input? Not a problem if you don’t, though.

Hmm, so if I do have multiphase abilities, I’ll need to have a custom ability subclass to handle skipping to a specified phase on load. I’ll keep that in mind. I’m not sure yet if I need multiphase abilities.

Yes, I think the gameplay effects are indeed easier to save than the abilities, probably. They don’t have the whole instancing thing going on. Though it’s technically possible to dynamically construct and apply a gameplay effect at runtime, that’s usually frowned upon from what I understand. That said, even if it’s frowned upon, it barely complicates the process at all.

Loose tags are a tricky one. From what I can tell, the ASC makes no distinction between loose tags and tags from effects. I’m not sure yet whether I’ll want to use them, but if I do, I think what I might need to do is add wrapper functions in my custom ASC subclass that separately keep track of the loose tags while also pushing them through to the superclass calls managing them.

I’m not sure I understand this. What is a preset and the default attributes for a preset? Seems like something fairly specific to your game, or am I missing something?

My current WIP saves the base value of all attributes that exist on the ASC. I think it’s a bit excessive, but I’ve yet to think of a way to cut it down further.

just to make it clear: it’s hard to generalize some things, so in some cases i’m talking about my particlar project, which is RTS-like, which may not be applicable to your case.

That’s a hard to put in words, but i think it’s not quite it. Anyway, anything that will work is okay.

That’s correct. Unless you doing turn-based game where you can enforce “no abilities is currently running” you have to save them to load game in correct state (in the middle of ability usage)

I mean, GA’s execution is determined by world state, avatar actor, ability class and params passed to ActivateAbility().

  • World state (generally - the actors presense and locations) should be set up before loading abilities and out of scope of this question
  • Avatar actor & Ability class - kinda trivial in context of saving\loading state of particular actor
  • params passed to ActivateAbility() - exactly what i mean by Inputs. If you activate abilities with no params - there is no inputs; If you use targeting to generate inputs mid-execution - that would require some extra tricks to save those (ex. save new inputs and don’t request targeting if target is already known)
    • Worth noting that i mean “inputs\params” conceptually, not literally. I’m include any additional settings you made to ability instance at runtime before calling Activate. // This clarification may not even be relevant to you, but if you doing a bunch of custom activation setups - it surely is

That’s kinda hard to imagine that even phase “get closer to target and then start” is not applicable. But probably possible

That’s what i’ve heard, yes. Iirc the only real problem is network replication, but even then - never need them in my cases

To give you idea:
a unit has a set of params: maxhp, attack, defence, etc.
the map of presets is a table:

warrior: 100, 10, 5
rogue: 50, 15, 3
mage: 20, 20, 0

On my actor instance i can just set it “this one is Warrior”. Then custom ASC init would pull data from table and set the maxph, attack, defence to 100, 10, 5.
This way instead of saving a dozens of BaseValue of attibutes you may save just a single FString “warrior”.
After that, any lvlup bonuses, equipment bonuses, etc, are handled by corresponding systems by applying GEs to modify CurrentValue of attributes.

That’s surely specific for my game, but i think this concept may be applied widely. I don’t force it, just giving it as an idea\example

So you’re saying level up bonuses are just a GE for you? If I go that way I might be able to entirely skip saving attributes, since I don’t have classes – the initial attributes would be the same for every player (monsters/npcs would have different ones, but those are determined by the monster/npc definition).

That’s the case where it’s surely possible to solve problem by several different ways and every way will be a correct one. So think twice if you really want to switch your already existing system to this one.

But yes, in my particular case - that’s the case iirc.

No switching needed – I haven’t even implemented level ups yet. But I will think twice about whether or not I want to do it with a gameplay effect.