Search Issue Tracker
By Design
By Design in 2023.2.X
Votes
0
Found in
2021.3.16f1
2022.2.2f1
2023.1.0a25
2023.2.0a1
Issue ID
UUM-22811
Regression
No
New instance of a material is created when calling "Resources.UnloadAsset" in the same frame as unloading a scene
Reproduction steps:
1. Open project “case_1343272-AMemoryTest”
2. Open scene “Boot”
3. Enter Play Mode
4. Click the “Unload” button
5. Open “Window\Analysis\Memory Profiler”
6. Click “Capture New Snapshot”
7. Open the captured snapshot and go to “Unity Objects”
8. Find “M01” under “Material”
Expected result: the “M01” material doesn't appear in the Memory Profiler because it has been unloaded
Actual result: the “M01” material appears in the Memory Profiler
Reproducible with: 2021.3.16f1, 2022.2.2f1, 2023.1.0a25
Couldn’t test with: 2020.3.43f1 (due to compiler errors)
Reproducible on: macOS Catalina 10.15.7 (Intel)
Note: Also reproduced in Player
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Out-of-bounds memory access with multiple CanvasRenderers under a Canvas when using Mesh API
- Inspector tries to access file after it was deleted when the file was locked in Inspector window
- Changing Transform values in Search window Inspector loses focus while dragging and stopping mouse without releasing dragging action
- Saving changes on the dirty VFX Graph during the Play mode throws "The referenced script (Unknown) on this Behaviour is missing!" warnings
- VFX Graph Debug Info overlaps the "Initialize" block debug info by default
Resolution Note:
Unloading a scene is async, which means we get at least one repaint of the scene before the objects are destroyed. This repaint will reload any neeeded material assets, which is what is happening here.
So the unloading of the material needs to be delayed otherwise the material will be reloaded on the next repaint.
This can be fixed using a coroutine like this:
public class Tester : MonoBehaviour
{
// This can used manual testing
[MenuItem("Bug/Unload Unused Assets")]
static void UnloadUnused()
{
EditorUtility.UnloadUnusedAssetsImmediate();
}
void Start()
{
SceneManager.LoadSceneAsync("Scenes/Test01", LoadSceneMode.Additive);
SceneManager.LoadSceneAsync("Scenes/Test02", LoadSceneMode.Additive);
}
public void Unload()
{
var go = GameObject.Find("Cube");
var r = go.GetComponent<Renderer>();
var mat = r.sharedMaterial;
var scene = SceneManager.GetSceneByName("Test01");
SceneManager.UnloadSceneAsync(scene, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
StartCoroutine(ExecuteAfterTime(0.1f, mat));
}
IEnumerator ExecuteAfterTime(float time, Material materialToUnload)
{
yield return new WaitForSeconds(time);
// Code to execute after the delay
Debug.Log("Unloading asset");
Resources.UnloadAsset(materialToUnload);
}
}
Resolution Note (2023.2.X):
Unloading a scene is async, which means we get at least one repaint of the scene before the objects are destroyed. This repaint will reload any neeeded material assets, which is what is happening here.
So the unloading of the material needs to be delayed otherwise the material will be reloaded on the next repaint.
This can be fixed using a coroutine like this:
public class Tester : MonoBehaviour
{
// This can used manual testing
[MenuItem("Bug/Unload Unused Assets")]
static void UnloadUnused()
{
EditorUtility.UnloadUnusedAssetsImmediate();
}
void Start()
{
SceneManager.LoadSceneAsync("Scenes/Test01", LoadSceneMode.Additive);
SceneManager.LoadSceneAsync("Scenes/Test02", LoadSceneMode.Additive);
}
public void Unload()
{
var go = GameObject.Find("Cube");
var r = go.GetComponent<Renderer>();
var mat = r.sharedMaterial;
var scene = SceneManager.GetSceneByName("Test01");
SceneManager.UnloadSceneAsync(scene, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
StartCoroutine(ExecuteAfterTime(0.1f, mat));
}
IEnumerator ExecuteAfterTime(float time, Material materialToUnload)
{
yield return new WaitForSeconds(time);
// Code to execute after the delay
Debug.Log("Unloading asset");
Resources.UnloadAsset(materialToUnload);
}
}