Search Issue Tracker

By Design

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

  1. 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);
    }

    }

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.