当我们使用 Unity Profiler
查看内存时,经常有些贴图等资源的引用只有一个 ManagedStaticReferences()
引用,怎么都卸载不掉。
使用 Memory Profiler
也查找不到谁引用的。现在终于找到方法,开心,来分享给大家。
具体思路:
- 维护一个 key 是 物件
Hierarchy
路径, value 是WeakReference
的字典,收集所有可能会泄漏的组件 - 在需要 Check 的物件挂靠的脚本里 添加该
Componet
的 弱引用到字典 - 查看 Alive 状态,Alive 为 true ,但 target 为空的即为泄漏者,打印他的路径
- 如果单纯查找 UI 贴图的内存泄漏,例如 NGUI 可以只在
UIWidget
的 Awake 里添加弱引用到字典, UGUI 的话需要下载 UGUI 源码 在Graphic
构造里添加引用,再打包 dll 来测试。这样就可以覆盖所有 UI 贴图 - 其他的,怀疑那个脚本,就把他的引用添加到字典里
代码如下:
public class ComponentReferenceManager
{
public static ComponentReferenceManager Instance = new ComponentReferenceManager();
Dictionary<string, WeakReference> refs = new Dictionary<string, WeakReference>();
private int count = 0;
public void AddRef(Component c)
{
var key = string.Format("Index:<color=red>{0}</color> ComponentType:<color=red>{1}</color> GameObject:<color=red>{2}</color>",
count, c.GetType().ToString(), GetGameObjectPath(c));
refs[key] = new WeakReference(c);
++count;
}
private string GetGameObjectPath(Component c)
{
var obj = c.gameObject;
string path = "/" + obj.name;
while (obj.transform.parent != null)
{
obj = obj.transform.parent.gameObject;
path = "/" + obj.name + path;
}
return path;
}
public void PrintLog()
{
GC.Collect();
Debug.LogError("打印销毁了但还被引用的物件:");
foreach(var kv in refs)
{
if (kv.Value.IsAlive)
{
if (kv.Value.Target == null)
{
Debug.LogErrorFormat("Target is null {0}", kv.Key);
continue;
}
var w = kv.Value.Target as Component;
if (w == null)
{
Debug.LogErrorFormat("Component is null {0}", kv.Key);
continue;
}
if (w.gameObject == null)
{
Debug.LogErrorFormat("Component attached game object is null {0}", kv.Key);
}
}
}
}
}
在 UIWidget
的 Awake 里 或者你怀疑的其他脚本里添加调用
#if UNITY_EDITOR
ComponentReferenceManager.Instance.AddRef(this);
#endif
编辑器脚本
public partial class ReportEditor
{
[MenuItem("Jinggle/打印销毁了但还被引用的物件")]
static void ReportUIRef ()
{
ComponentReferenceManager.Instance.PrintLog();
}
}
这样就会找到所有在场景里已经销毁了,但还是被引用到的物件了。 下一步就是要查为什么明明被销毁了,还会被引用的原因了。
经过我排查我们游戏,发现导致 ManagedStaticReferences()
绝大部分原因都是 static 变量的使用不当。
真真儿是 静态变量一时爽,内存泄漏火葬场。
–EOF–