加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Unity内存分析-Texture引用计数-如何让UI界面在Destroy时释放掉手动挂上去的静态资源(如背景图)

(2016-07-10 10:42:10)
标签:

texture引用

内存回收

分类: 修炼Unity
写博客之前我们先来看三张图
图一:游戏刚运行时,在Hierarchy视图中可以看到,我还没有创建Cube1,所以此时Profiler中没有Texture2D的引用

图二:此时我点击了按钮“Create Cube1”创建Cube1,在Hierachy视图中可以看到,并且上面挂了一个UISprite脚本,此时Profiler视图中,已经有了图集TextureAtlas的引用(引用数为7)

图三:点击“Destroy”按钮销毁Cube1,在Hierrachy视图中可以看到Cube1已经不存在了,
此时Profiler视图中,TextAtlas的引用仍然存在(引用数为1)!!!! 这里的TextAtlas图集占用内存比较小,只有170.8KB,但是如果占用8M呢,那么这8M就会在切换场景之前使用存在在内存里,如果玩家在主城中频繁点击页面,又会有其他图集的引用,这样很快,内存就不够用了,低端机尤为明显
http://s3/mw690/0028zgIhzy738C5Rb1wf2&690


下面就讲一讲如何解决这种情况??
通过Profiler我们可以分析出TextAtlas是被Material引用着。是不是能有启发呢?
在UI页面显示时,我们可以收集该页面及其所有子节点的Material,如下我写了一个PanelResources的脚本,其中的MMats(List)收集的就是PAw_Award下的所有material.

这样在页面销毁时,我们就会便利MMats(List)
for(int i = 0; i < MMats.Length; i ++)
{
      MMats[i].SetTexture("_MainTex", null);
}

此时我们再看Profiler监测,TextAtlas引用计数是不是为0了,这个时候在上面的这个循环后边加两行代码:
Resources.UnloadUnusedAssets();
System.GC.Collect(); 才能实现真正的内存回收(就是又会出现图一情况了)
注意,注意,这个时候还没有结束,我们再次点击"Create Cube1"按钮,你会发现虽然Cube1创建出来,但是没有背景图了,查看TextAtlas,确实没了,这是因为
for(int i = 0; i < MMats.Length; i ++)
{
      MMats[i].SetTexture("_MainTex", null);
}
将贴图给置空了,你也许会很疑惑,我先在重新创建了一个Cube1,对应的材质引用啥的,应该是新的,应该有Texture才对,为啥没了?? 这是因为Texture是个引用而不是复制,所以你在循环中置空,会直接影响到原图
这时候你在Project视图中查看确实如此。

这又怎么解决呢?
在页面显示时,我们收集了Material到MMats中,Material的贴图通过代码赋值上去,岂不就解决了

此外:我们可以把收集Material代码在编辑模式下完成。

总结:
1. 编辑模式下:收集Material至MMats
2. 创建页面时,
for(int i = 0; i < MMats.Length; i ++)
{
      MMats[i].SetTexture("_MainTex", xx);
}
2. Destory页面时,
for(int i = 0; i < MMats.Length; i ++)
{
      MMats[i].SetTexture("_MainTex", null);
      //当然如果该材质还有其他贴图,则也许要置为null,有没有其他的这是由Shader决定的
      MMats[i].SetTexture("_AlphaTex", null);
}
Resources.UnloadUnusedAssets();
System.GC.Collect();

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有