Search Unity

[UWP] Resources.UnloadUnusedAssets() behaves differently against WeakReference

Discussion in 'Windows' started by bboydaisuke, Jul 19, 2016.

  1. bboydaisuke

    bboydaisuke

    Joined:
    Jun 14, 2014
    Posts:
    67
    Let me share a problem I got hit. Though I fixed it already for my app, I think better share because it is difficult to find.

    PROBLEM
    WeakReference.Target becomes null on UWP earlier than mono.
    As far as I researched, Resources.UnloadUnusedAssets() behaves differently against WeakReference as follows:
    • WeakReference.Target becomes null on GC.Collect() after Resources.UnloadUnusedAssets() on mono
    • WeakReference.Target becomes null on Resources.UnloadUnusedAssets() on UWP

    STEPS TO REPRODUCE

    Use this code or attached project.

    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class NewBehaviourScript : MonoBehaviour {
    7.     List<WeakReference> m_weakReferenceList;
    8.  
    9.     void Start()
    10.     {
    11.         Clear();
    12.     }
    13.  
    14.     public void FireGC()
    15.     {
    16.         GC.Collect();
    17.         Debug.Log("GC.Collect() is executed.");
    18.     }
    19.  
    20.     public void UnloadUnusedAssets()
    21.     {
    22.         Resources.UnloadUnusedAssets();
    23.         Debug.Log("Resources.UnloadUnusedAssets() is called.");
    24.     }
    25.  
    26.     public void Clear()
    27.     {
    28.         m_weakReferenceList = new List<WeakReference>();
    29.         Debug.Log("WeakReference list cleared.");
    30.     }
    31.  
    32.     public void Add()
    33.     {
    34.         GameObject go = Resources.Load("Prefab") as GameObject;
    35.         m_weakReferenceList.Add(new WeakReference(go, true));
    36.         Debug.Log("WeakReference added to WeakReference list.");
    37.     }
    38.  
    39.     public void ShowInfo()
    40.     {
    41.         for (int i = 0; i < m_weakReferenceList.Count; i++)
    42.         {
    43.             if (m_weakReferenceList[i].Target != null)
    44.                 Debug.LogFormat("m_weakReferenceList[{0}].Target is NOT null.", i);
    45.             else
    46.                 Debug.LogFormat("m_weakReferenceList[{0}].Target is null.", i);
    47.         }
    48.     }
    49. }
    50.  
    • Build it to UWP VS project.
    • Call Add() -> UnloadUnusedAssets() -> ShowInfo() on both mono (Unity Editor) and UWP.
    • On mono, m_weakReferenceList.Target is NOT null.
    • On UWP, m_weakReferenceList.Target is null. (behaves different than mono).
    • On mono, Call additionally FireGC() -> ShowInfo(). m_weakReferenceList.Target will be null.
    NOTES
    Though I read through the reference, I can't tell which behavior should be. However, this difference is a breaking change and caused various problems to my app.

    UNITY VERSION
    5.3.5p7
     

    Attached Files:

  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,735
    When you UnloadUnusedAssets(), those objects you have weak references to become eligible for garbage collection. GC is itself unpredictable in terms of timing and your code should not rely on it's timing.
     
  3. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I thought that internally, Resources.UnloadUnusedAssets called GC.Collect