See what each rename needs
Saves hold properties, struct members, enum values and gameplay tags by name, and classes and assets by path. After a rename, the old name in a save matches nothing unless a redirect says where it went. Play In Editor hides some of these problems, because the editor keeps records of renames that a packaged game does not have, so check renames in a packaged build.
| You rename | In a packaged game, with nothing added | Add |
|---|---|---|
| A C++ property, or a member of a C++ struct | The value loads as its default | +PropertyRedirects |
| A C++ struct type, held by a property | The value loads as its default, with “has a struct type mismatch” in the log | +StructRedirects |
| A C++ struct type, held by an instanced struct or a property bag | The value loads empty, with “Unable to find serialized UScriptStruct” in the log | +StructRedirects |
| A value of a C++ enum | The enum loads as an invalid value one past its last (the enum’s hidden _MAX entry), with a warning in the log |
+EnumRedirects with ValueChanges |
| An entry of a Blueprint enum, in the enum editor | Nothing is lost: the editor changes the name you see and keeps the name saves hold | Nothing |
| A member of a Blueprint struct, in the struct editor | Nothing is lost: saves hold each member’s ID beside its name | Nothing |
| A Blueprint variable | Loads when every build that wrote and reads the save cooked the Blueprint’s property IDs; otherwise loads as its default, though Play In Editor loads it | Cooked property IDs from the first release on; for saves written without them, +PropertyRedirects |
| A gameplay tag | The tag loads under its old name, which the game no longer has | A gameplay tag redirect |
| The C++ class of an object a saved object owns | The owned object loads empty | +ClassRedirects |
| The class of a Save Handler a Save Rule or Rolly Save component attaches | The handler’s record is kept and not applied, so the handler starts empty | +ClassRedirects with the class’s path (_C for a Blueprint); the record’s save ID holds the old path, which the redirect reaches, and the next save writes it under the new one |
| A Blueprint class, renamed or moved | A pointer to it, and an object of it that a saved object owned, load empty | +ObjectRedirects or +ClassRedirects with the class’s path, which ends in _C; a soft reference to it follows object and package redirects only |
| An asset moved to another folder | A pointer to it loads empty | +PackageRedirects |
| An asset renamed | A pointer to it loads empty | +ObjectRedirects |
Reordering enum values, properties or struct members needs nothing: saves match them by name.
Add a redirect
Add redirects to Config/DefaultEngine.ini under [CoreRedirects] before you ship the renamed build, and keep them for as long as players may hold saves from before the rename. Packaged Development and Shipping builds both read them.
[CoreRedirects]
; A property of UInventory renamed from Coins to Gold: the class name without its U.
+PropertyRedirects=(OldName="/Script/MyGame.Inventory.Coins",NewName="Gold")
; A member of the C++ struct FItemStack renamed from Amount to Count: the struct name without its F.
+PropertyRedirects=(OldName="/Script/MyGame.ItemStack.Amount",NewName="Count")
; The C++ struct FOldReward renamed to FReward, wherever a property, an instanced struct or a property bag holds it.
+StructRedirects=(OldName="/Script/MyGame.OldReward",NewName="/Script/MyGame.Reward")
; A value of EItemRarity renamed from Emerald to Green.
+EnumRedirects=(OldName="/Script/MyGame.EItemRarity",ValueChanges=(("EItemRarity::Emerald","EItemRarity::Green")))
; A class of owned objects renamed from UOldQuest to UQuest.
+ClassRedirects=(OldName="/Script/MyGame.OldQuest",NewName="/Script/MyGame.Quest")
; A data asset moved from Items to Weapons, keeping its name.
+PackageRedirects=(OldName="/Game/Items/DA_Sword",NewName="/Game/Weapons/DA_Sword")
; A data asset renamed: the full path of the old and the new object.
+ObjectRedirects=(OldName="/Game/Items/DA_Sword.DA_Sword",NewName="/Game/Items/DA_Blade.DA_Blade")
; A Blueprint class renamed: the path of its class, which ends in _C.
+ObjectRedirects=(OldName="/Game/Quests/BP_OldQuest.BP_OldQuest_C",NewName="/Game/Quests/BP_Quest.BP_Quest_C")A package redirect changes only the folder and package name: an asset that was also renamed needs an object redirect with both full paths instead.
For a Blueprint class, +ClassRedirects with the same paths, the form Epic’s Core Redirects documentation shows, works for pointers and owned objects too. A soft reference to the class, such as a TSoftClassPtr, follows object and package redirects only, so +ObjectRedirects covers every reference a save holds.
A load finds a redirected asset at its new path and loads it from there, also when nothing in the game has loaded it yet.
Rename a gameplay tag
Add the redirect in Project Settings > Project > GameplayTags > Gameplay Tag Redirects, with the old tag as Old Tag Name and the new one as New Tag Name. It is saved to Config/DefaultGameplayTags.ini:
[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagRedirects=(OldTagName="Item.Ore",NewTagName="Item.Iron")The new tag must exist. Tags in tag containers follow the redirect too.
Rename a Blueprint struct member
Rename it in the struct editor: nothing else is needed, in Play In Editor and in packaged games. Each member keeps an ID when it is renamed, saves hold the ID beside the name, and a load finds the member by its ID. Engine save games lose renamed struct members in packaged builds; Rolly Save keeps them.
Renaming the struct asset itself needs nothing where a property of your class holds it. Where an instanced struct or a property bag holds it, add an +ObjectRedirects entry with the struct’s old and new path.
Rename a Blueprint variable
A packaged game finds a renamed Blueprint variable by the ID a save holds beside its name, and a build writes and reads those IDs only for Blueprints cooked with them, which is off by default. A save written by a build without them holds names only, and no later build can match it by ID. So turn the IDs on before your first release and keep them on in every build that writes or reads saves:
- In each Blueprint whose variables saves hold, open Class Settings and set Should Cook Property Guids? to Yes.
- Or, for every Blueprint at once, set Project Settings > Engine > Cooker > Cook Blueprint property GUIDs? to All Blueprints, which costs a little memory per Blueprint class.
If your game already shipped without them, players’ saves hold variable names only. Add a property redirect with the path of the Blueprint’s class for each variable you rename: +PropertyRedirects=(OldName="/Game/Chests/BP_Chest.BP_Chest_C.OldName",NewName="NewName"). Turning the IDs on in a later build restores nothing in those saves; it makes saves written from that build on survive later renames without a redirect.
Play In Editor finds renamed variables either way, so check the rename in a packaged build.
Rename a property saved by path
A value a Save Rule or a Rolly Save component saves by path is held under the names of its property and members, with its type, and without property IDs.
- A C++ property or a member of a C++ struct: add
+PropertyRedirectsas above and change the Saved by Path entry to the new name. A load finds the value under its old name through the redirect. - A Blueprint variable: add
+PropertyRedirectswith the path of the Blueprint’s class, as for a game shipped without cooked property IDs, and change the entry. A variable with SaveGame ticked follows Rename a Blueprint variable instead. - A changed type, a renamed struct or enum type included:
+StructRedirectsand+EnumRedirectsdo not reach these values. Without a migration step a load skips the value with PathNotApplied and keeps the live one, and the next save writes the live value. Add a step that reads the value with Get Path Value as its old type and writes it back with Set Path Value as the new one (see Keep old saves loading).