If ScriptableObject once opened in inspector its persist in editor memory forever

If you have empty scene, and open any ScriptableObject in inspector, than close it,
OnBeforeSerialize of this ScriptableObject will be called each time you do any code changes in your project even if it not related to this SO.

I have massive SO that represent graph with nodes. And it took 40 seconds Reload Domain each time I do any code changes in my project, because I have reference to this SO in my scene. Even if I do not have references but once opened graph SO in inspector, it start keep getting into Reload Domain no matter what.

This is a feature, not a bug.
SOs are persistent throughout the lifetime of the game.
The reason OnBeforeSerialize is called is because the entire domain is reloaded when you recompile.

What you could do is check whether the Application is running inside your OnBeforeSerialize (which would only be required inside the editor, so you could envelope this check in a #if UNITY_EDITOR so it’s not present in a build).
That would reload only when you enter PlayMode.

The problem is only about Editor mode. It is not related to Play Mode at all. Why should I wait this SO will reloaded each time my code recompiled if I only once opened it in inspector and close it. I don’t have references to this SO in my scene.

Just checked, and apparently you’re not allowed to check Application.isPlaying in a OnAfterDeserialize (though you are allowed to check it in OnBeforeSerialize?).

Because the entire object is considered to be a ‘SerializedObject’. It’s loaded as soon as you open the inspector.

The inspector window doesn’t talk to the C# api to figure out what the values of the properties of whatever it is inspecting is. It asks the object to serialize itself, and then displays the serialized data. Once serialized, the SO will persist.

So my question than is it possible to remove it from the memory so it is not getting into Reload Domain?

Are you using a custom editor?
If so, you could try Resources.UnloadAsset() in the OnDisable/OnDestroy of your editor.

1 Like

I test it with new clean project, simple scriptable object from documentation. How do I get reference to SO that unity load in memory when inspector was opened in order to Resources.UnloadAsset()? I don’t think there is a way.

Unity re-serialises all assets assets on domain reload, which is a part of it resetting the overall ‘state’ of everything. Worth noting that domain reloads do a lot more than just recompile code, which is just a very small part of the overall process.

I’ll also note that Unity serialises and deserialises assets open in the inspector every repaint too, so you’ll probably be experiencing issues here.

If large serialised assets are causing issues with recompiling, I recommend saving the pure C# data as a binary asset that you access only when necessary. As Unity can’t and won’t to attempt to serialise the binary asset, it won’t be a part of domain reloads. This is common practice when working with large amounts of data.

1 Like

You can find all loaded instances of your object by calling Resources.FindObjectsOfTypeAll<YourScriptableObject>(), then calling Resources.UnloadAsset() on them.

EDIT: Missed the context that this was in an inspector. @SF_FrankvHoof is correct that you can use the editor target as the argument for UnloadAsset. No FindObjects call needed.

this.target is the object

1 Like

Actually you should not try to fight against major Unity features. If the serialization of your nodes is slow, you may try including a “version” int in your object. Whenever you actually change your nodes you would increase the version. That way you can compare it to a serialized version and only reserialize / convert your node structure to the serializable data when the version has changed. Of course the object still needs to be deserialized if it’s still loaded in memory after an assembly reload. Though you could avoid unnecessary re-serializations that way.