- Home /
How to destroy Scriptable Objects on Reimport
Hi,
I have a native plugin in c++ that creates and manages some allocated user data.
A reference to this data created is held by an scriptable object (which is supposed to be shared among several components) I am taking care of the memory management OnAwake/OnEnable and OnDestroy/OnDisable.
An instance of the scriptable object is created when I import some custom asset format. Everything works fine, until when I need to reimport this asset.
Basically, I create a new instance of the object in the body of the importer, and (I suppose) Unity internally replaces the old reference with the new one.
The problem is when this done, the OnDestroy (or OnDisable) is never getting called again, so my user data is never destroyed and it causes a small memory leak (it happens only on the editor, and when I reimport the asset, so it is not so critical)
as a workaround, I am keeping a static dictionary that holds the asset file name as key, and the scriptable object reference as value. When I detect that a reimported asset, I directly call the destructor of the user data.
besides being cumbersome, when the importer script itself is reloaded, the static data is cleared, so I still have this corner case memory leak.
ideally, i wanted to rely on the OnDestroy only, so how should I properly reimport the asset so that the SO gets destroyed?
Answer by YetAnotherKen · Sep 09, 2019 at 07:38 PM
I have noticed that Unity expects an asset not to be destroyed if you want to use it again. You can get around that with Object Pooling.
Another angle is to make sure you have destructors defined for the classes that contain data you want to re-instantiate later. This makes you rely on the garbage collector which is not ideal if you need speed. If you make the class inherit from IDisposable then you can use that to flag the objects for garbage collection and implicitly get the destructor to run.
If this is the case, I guess there is not much else to do (the whole importer thing is still experimental, so I think they will change the API in a near future)
even if they recicle the asset and OnDestroy is not supposed to be called on reimport, at least I would expect OnDisable to be called (since the SO was enabled before)
I don't think the destructor would be nice in my case, because I don't know when Unity is using local instances to copy the data around...
I was watching a talk about SOs and at some point it is mentioned "Resources.UnloadUnusedAssets" could be used for some cleanup. I am new to the API, so I'm not sure how good it is to use it (it would be nice a solution that does not interfere with other unrelated objects)
anyway, thanks. I will wait a bit more for other comments before closing this question.
What I mean is ins$$anonymous$$d of using Destroy I would deactivate the GameObject by using something like this:
public void ClearFlora(List<FloraRecord> _floraRecords)
{
for (int index = _floraRecords.Count-1; index > -1; index--)
{
_floraRecords[index].floraItem.SetActive(false);
}
}
Then to reactivate them:
public void RespawnFlora(List<FloraRecord> _floraRecords)
{
StartCoroutine(ProcessRespawn(_floraRecords));
}
IEnumerator ProcessRespawn(List<FloraRecord> _floraRecords)
{
if (meshObject.transform != null)
{
if ((meshObject.activeSelf) && (myChunk.initialSpawn))
{
for (int index = _floraRecords.Count - 1; index > -1; index--)
{
_floraRecords[index].floraItem.SetActive(true);
_floraRecords[index].floraItem.transform.parent = meshObject.transform;
}
}
}
yield return new WaitForEndOfFrame();
}
You don't have to use a Coroutine like I have done in this example.
Your answer
Follow this Question
Related Questions
[CreateAssetMenu] For inherited ScriptableObjects 1 Answer
Interface on ScriptableObject 1 Answer
Skill system where every skill has unique functionality? 1 Answer
Assigning scriptable objects to dictionary through array? 0 Answers
Instancing ScriptableObject not saved in assets results in warning message 0 Answers