Changing variable to array and keep Serialization

Hey ererybud’

I know you can change a variable name and keep Unity Serialization like this:
public string myString
to
[FormerlySerializedAs("myString")]public string myNewString

But what I need to do is, change:
public string myString to –> public string[ ] myStrings

Any chance to keep the old myString value as the first entry? I know its an operation on the open heart, but our localisation system needs to get multiple keys now, we have several hundred text components already fed with keys, rewriting them is not an option.

If this would be the case I would add a dirty public string myString2 public string myString3

Hope some veterans have a Idea!

PS: In such cases I always think about maybe creating an editor script, but the fact that this needs to be done in all scenes seems very dirty as-well. You would have to open every last scene for it to work, and you mess up if you forget one. I guess it’s not possible to run editor scripts in unopened scenes right?

ISerializationCallbackReceiver:

public class YourClass : MonoBehaviour, ISerializationCallbackReceiver {
     public string myString;
     public string[] myStrings;

     public void OnBeforeSerialize() {}
     public void OnAfterDeserialize() {
         if (!string.IsNullOrEmpty(myString)) {
             myStrings = new string[] { myString };
             myString = "";
         }
     }
}

If you use AssetDatabase.ForceReserializeAssets to reserialize all scenes and prefabs, you should be good, as long as there’s not other people commiting those kinds of assets. ForceReserializeAssets ensures that the asset’s file is up to date.

It’s pretty straight forward to use:

var pathToAllScenes = AssetDatabase.FindAssets("t:scene").Select(AssetDatabase.GUIDToAssetPath).ToArray();
var pathToAllPrefabs = AssetDatabase.FindAssets("t:prefab").Select(AssetDatabase.GUIDToAssetPath).ToArray();

AssetDatabase.ForceReserializeAssets(pathToAllScenes);
AssetDatabase.ForceReserializeAssets(pathToAllPrefabs);

My workflow for stuff like this is:
1: create the ISerializationCallbackReceiver implementation, and make sure all code only touch the array
2: (if on a team): wait until everyone on the team has merged it, so they’re not creating assets with the non-array field
3: force reserialize all scenes and prefabs
4: go through git status (or whatever equivalent you’re using) and check that everything looks like it’s been transfered properly
5: delete the ISerializationCallbackReceiver implementation

You might want to run the force reserialize all code once first, if you haven’t done that before, as you’ll have a lot things that will be updated due to that, and it’ll make it hard to do part 4 when there’s so many other things floating around.

2 Likes

Wow, this is on point, some serious pro tips here! :stuck_out_tongue:

I’ll try to give it a shot, but every other developer is crawling out of its grave at the moment, so maybe I have to try today evening just to be safe :smile:
Thank you so much for this detailed explanation, there will most certainly be more people after me who will find this thread!