Undo.RecordObject is too slow on large arrays, alternatives?

I’m updating a single value in a Serialized byte array that is 1,000,000+ long.

So far, everything has been fine handling it.

I am changing these values through some input in the scene window (it’s a tile-painter) and using Unity.RecordObject so I can add Undo functionality (as stated in the guide for writing sell-able assets). This function says it records the Delta changes and I wrongly assumed that meant: the changed indexes and their value from an array, but I think it means it only looks at each property that changes. So obviously, every time I call this, it checks a massive array for changes and I assume it does a whole bunch of serializing/deserializing. This causes a 5m-1000ms delay when trying to use my application…

What are my alternatives? I have tried splitting the data out over multiple serialized scriptable object instances. This works and is fast, the only downside is, I now have 100+ scriptable objects just sat in my asset folder. This is now very ugly to use.

Is there a method I can use to store them as serialized objects, without needing multiple objects in my asset folder? E.g. someway to bury each object as an individual property in a prefab? I can’t just write a monster class with 100 arrays on it, as the world size is variable.

I don’t know much about the efficiency of RecordObject on large arrays. But a way you can clean up the 100+ scriptable objects in your asset folder is to combine them.

Create a root .asset (ScriptableObject file) and when you create the other files add them to the root file using AssetDatabase and then hide them so they won’t show up in the folder (you should also probably add a reference to each of them to a variable in the root asset). You can then access all the assets through your custom editor window by loading up the root file only.

Example:

Root rootAsset;

private void AddNewAsset(SubAsset newAsset)
{
    AssetDatabase.AddObjectToAsset(newAsset, rootAsset);
    newAsset.hideFlags = HideFlags.HideInHierarchy;
}