前言

最近进行项目性能优化的时候发现的问题。

问题

从大厅进到单局的过程中,会经过选择英雄和加载两个流程,这两个流程对应的UI界面都会有一张几mb左右的贴图作为背景,在进入单局游戏后这两个UI已经销毁了。

之后调用下对应的Resources的相关接口,按理来说图集贴图就应该释放掉了。

Resources.UnloadUnusedAssets()

然而并没有,用Profiler检查了,发现被父级的层级Layer里的GraphicRaycaster引用了(比如下图的英雄界面背景)。

基本上每次进单局都有10mb左右的内存没释放掉

问题排查

暴力重建

项目主程给我的建议把这层Layer直接Destroy掉重建,这样确实能解决问题,但是有可能摧毁的时候上面还有其他UI,导致UI注册信息还在相关的gameObject却没了,访问UI的时候会抛出NullReference的异常,所以这个方法太简单暴力了,不好。

查阅源码

尝试阅读了GraphicRaycaster的源码,发现它内部维护了两个Graphic的列表

这两个列表只有在发起一次新的射线的时候才会清空(进单局后选人和加载的Layer子节点下不会有新的UI接受触摸射线了),于是猜测可能是List一直没清空导致的图集无法释放。

emmmmm,官方还打上了反序列化的标签,这样编辑器的Debug模式下也无法查看这两个List的数据了。

没办法,拷贝了整个代码到一个新类TestGraphicRaycaster,把这两个标签替换为SerializeField,然后把相关Layer上的GraphicRaycaster用这个脚本替换了下,然后运行游戏。

果然跟猜测的一样,是m_RaycastResults这个列表保存的Graphic没有Clear掉,这样Graphic无法被GC回收,进而导致Graphic持有的图集也无法被释放掉。

找到问题了,那就好解决了。

解决方法

直接清理列表

创建一个新类,把GraphicRaycaster的源码拷贝到新类当中,然后添加一个清理的接口

public void ClearRaycastResults()
{
if(m_RaycastResults != null)
{
m_RaycastResults.Clear();
}
}

使用反射清理列表

如果你没有源码或者不想修改源码,那么用反射获取对应的列表清理也是可以的。

using System.Reflection;

//放在你的工具类里

public static void ClearRaycastResults(GraphicRaycaster gRaycaster)
{
if(gRaycaster != null)
{
var fieldInfo = gRaycaster.GetType().GetField("m_RaycastResults", BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.Instance);
if (fieldInfo != null)
{
List<Graphic> list = fieldInfo.GetValue(gRaycaster) as List<Graphic>;
if(list != null)
{
list.Clear();
}
}
}
}

然后在释放资源前调用下上述方法清理掉GraphicRaycaster的列表就行了 

参考资料

相关信息可以参考我在UnityAnswer上发布的这个问题

Unity3D学习(十一):关于UI销毁后图集仍然无法释放问题的解决办法的更多相关文章

  1. 关于hasNextInt判断后无限循环输出else项的解决办法

    话不多说,上来就是干! import java.util.Scanner; public class Test_hasNextInt { /** * @param args */ public sta ...

  2. WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转)

    WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转) Windows Communication Foundation (WCF)是Microsoft为构建面向服务的应用提供的分布式通信 ...

  3. windows7开机后,罗技k380无法自动连接解决办法

    问题描述: windows7开机后,罗技k380无法自动连接,必须删除设备后重新发现才能正常连接. 解决办法: 是因为笔记本电脑的蓝牙设置问题.按如下设置即可解决. [Bluetooth设置]-[允许 ...

  4. redhat图形界面启动后出现桌面但是没有登录界面解决办法

    redhat图形界面启动后出现桌面但是没有登录界面解决办法 2014年07月11日 10:50:10 阅读数:7931 redhat Linux一直用着好好地,今天打开只有图像界面背景,没有出现登陆界 ...

  5. 使用uni-app开发小程序,关于小程序更新后与用户本地不会及时更新解决办法

    1.原因分析 在小程序更新开发版本之后,用户本地并没有对之前版本的小程序进行删除,那么再进入小程序的时候的版本是不会发生变化的,这是由于发版是异步执行,因此新版本将会覆盖的比较慢,本质是小程序的启动方 ...

  6. 【原】安装Win7和Ubuntu双系统后,Win7耳机无声音的解决办法

    最近安装了Ubuntu的桌面版,作成了双系统,可是发现了一个问题:进入Win7后有时插耳机会没有声音,外放有声音.后来更新驱动也没有解决问题,最后在网上查到了解决办法. 产生原因:进入Ubuntu后, ...

  7. hadoop启动后jps查不到namenode的解决办法

    最近由于项目需要开始接触hadoop,在配置伪分布式启动后,jps查询进程发现少了namenode,而DataNode却存在. 下面是我的core-site.xml和hdfs-site.xml配置: ...

  8. idea 导入项目后 有的项目目录结构不展开解决办法

    如图:可能会出现这中国情况. 解决办法: 1.一般项目导入完成后,但是目录不展开, 2.出现这种情况一般情况下, 关闭idea close idea ,然后重新导入一遍就OK.

  9. PHP网站从Apache转移到Nginx后产生404错误的原因和解决办法

    原案例分析: 1.原来的网站在wamp环境下搭建完成,一切正常,上传到虚拟主机环境为lnmp,结果访问时可以打开主页,然后点其他页面全部报404错误: 2.经分析得出原因:原网站环境为wamp使用了伪 ...

随机推荐

  1. SPSS Clementine 数据挖掘入门1

    SPSS Clementine是Spss公司收购ISL获得的数据挖掘工具.在Gartner的客户数据挖掘工具评估中,仅有两家厂商被列为领导者:SAS和SPSS.SAS获得了最高ability to e ...

  2. 一个十分简洁实用的MD风格的UI主框架

    2017-5-23 详见:https://github.com/baiqiantao/CheesesquareSample MainActivity public class MainActivity ...

  3. Java实现图片的裁剪

    需求: 有一张位置大小的图片,现在需要根据这张原图得到指定尺寸的图片,且得到的图片要符合原先图片的比例,就是在原图的基础上等比例缩放得到图片后,在进行剪裁,这样保证得到的图片是原图的一部分,而不是将原 ...

  4. Netbeans配合xdebug调试

    http://xdebug.org/download.php 下载对应的xdebug的dll不知道php文件中的ext文件夹中 并且加入以下配置在php.info 然后重启apche zend_ext ...

  5. STL - 算法 - 普通拷贝

    list<, , , , , , , , }; vector<int> coll2; cout << "** collection 1: **" &l ...

  6. it-tidalwave-semantic-aux-1.0.13.jar下载

    今天来给大家分一下一下自己认为还是挺不错的jar包下载网址,it-tidalwave-semantic-aux-1.0.13.jar,作为java开发人员可能时时刻刻都在跟jar包打交道,即使这会用不 ...

  7. unity3d GameCenter的使用

    原地址:http://blog.sina.com.cn/s/blog_6b3661a901013zmh.html 因为开发的游戏需要支持GameCenter,老大把这活交给我来搞,于是俺就百度Goog ...

  8. 谈谈 Java 线程状态相关的几个方法

    http://blog.jrwang.me/2016/java-thread-states/ 发表于 2016-07-23 在 Java 多线程编程中,sleep(), interrupt(), wa ...

  9. [转载]编写高性能js

    一.执行效率 1. DOM 1.1 使用DocumentFragment优化多次append 说明:添加多个dom元素时,先将元素append到DocumentFragment中,最后统一将Docum ...

  10. 如何配置 Oracle VirtualBox 中的客户机与物理机网络

    当你在 Oracle VirtualBox 虚拟机软件 中安装了各种操作系统时,你可能需要实现物理机与虚拟机之间的相互访问. 在这篇文章中,我们将会以最简单明了的方式来说明如何配置客户机与 Linux ...