Image sprite is created programmatically
_image.sprite = Sprite.Create(texture, ...);
Should I destroy it before replacing with a new one?
P.S.
My question comes from these thoughts:
Unity components are destroyed when their scene objects are destroyed. Sprite is not a component, so it seems unclear to me if it will be destroyed somehow (when calling Resources.UnloadUnusedAssets
or when the scene is unloading) in case it is disconnected from the image (replaced with another one).
-
\$\begingroup\$ Have you tried replacing some hundreds or thousands of these in a loop without destroying them and observing the Profiler to see if your memory usage increases? \$\endgroup\$DMGregory– DMGregory ♦11/04/2024 01:24:33Commented Nov 4, 2024 at 1:24
2 Answers 2
I found this post: https://answers.unity.com/questions/919594/how-to-destroy-spritecreate-leak.html
It seems to indicate that the more problematic part if the Texture being used:
"Textures are not garbage collected."
But I suppose if you're reusing Textures that's probably not an issue. If it is in fact an issue, it sounds like calling Destroy
specifically is preferable to using Resources.UnloadUnusedAssets
.
-
\$\begingroup\$ Yes, I destroy textures that are created programmatically, but what about Sprite itself? It probably doesn't take much space, still it's unclear if it is destroyed automatically or not. \$\endgroup\$Serg– Serg10/27/2022 15:19:16Commented Oct 27, 2022 at 15:19
-
\$\begingroup\$ Can you profile the app? I'm not too familiar with the Unity profiler, but I do know it has one built in. I'm guessing it would be pretty trivial to loop over some sprite creation code and see if the memory shoots up. \$\endgroup\$11/01/2022 18:18:54Commented Nov 1, 2022 at 18:18
-
\$\begingroup\$ I'm not an expert in Unity profiler either, but I'll give it a try. \$\endgroup\$Serg– Serg11/02/2022 19:52:15Commented Nov 2, 2022 at 19:52
Just to give this old question a definite answer:
Yes, you should destroy dynamically-created Sprite instances when you're done with them.
How can we check this?
Add a script like this to your scene. This creates 50 new random sprites every frame.
public class SpriteTester : MonoBehaviour
{
public Texture2D tex;
Sprite[] _sprites = new Sprite[50];
// Update is called once per frame
void Update()
{
for (int i = 0; i < _sprites.Length; i++)
{
// DestroyImmediate(_sprites[i]);
_sprites[i] = Sprite.Create(
tex,
new Rect(Random.Range(0, 50), Random.Range(0, 50), Random.Range(1, 50), Random.Range(1, 50)),
new Vector2(Random.Range(0, 50), Random.Range(0, 50))
);
}
}
}
Open the Unity profiler by going to Window > Analysis > Profiler
and run your scene. You'll see the "Total Used Memory" creeping up slowly from the memory we're allocating for all these sprites.
Now uncomment this line:
DestroyImmediate(_sprites[i]);
This releases the memory associated with the old sprite before we allocate a new one. Run your scene again, and you'll see "Total Memory Used" stops climbing.
There's still some garbage collector churn though (about 2 KB for 50 sprites, or ~40 bytes per sprite), so this isn't free - avoid creating and destroying sprites frequently if you can reasonably cache/reuse them instead. But if you only need to do this occasionally, like during a level transition or when loading a mod, user-generated content, or other asset you can't predict in advance, 40 bytes per sprite won't break the bank. Just remember to destroy it when you're done with it!
What I want to demonstrate with this answer is not just whether we should destroy sprites, but that whenever you have any question about what costs more time or memory, the best way to answer that question is to profile it. It's often very easy to do so - this example only took about a dozen lines of code and 5 minutes to test. Writing the text of the answer took more time and thought. π
You must log in to answer this question.
Explore related questions
See similar questions with these tags.