Unity3D学习(十一):关于UI销毁后图集仍然无法释放问题的解决办法
前言
最近进行项目性能优化的时候发现的问题。
问题
从大厅进到单局的过程中,会经过选择英雄和加载两个流程,这两个流程对应的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销毁后图集仍然无法释放问题的解决办法的更多相关文章
- 关于hasNextInt判断后无限循环输出else项的解决办法
话不多说,上来就是干! import java.util.Scanner; public class Test_hasNextInt { /** * @param args */ public sta ...
- WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转)
WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转) Windows Communication Foundation (WCF)是Microsoft为构建面向服务的应用提供的分布式通信 ...
- windows7开机后,罗技k380无法自动连接解决办法
问题描述: windows7开机后,罗技k380无法自动连接,必须删除设备后重新发现才能正常连接. 解决办法: 是因为笔记本电脑的蓝牙设置问题.按如下设置即可解决. [Bluetooth设置]-[允许 ...
- redhat图形界面启动后出现桌面但是没有登录界面解决办法
redhat图形界面启动后出现桌面但是没有登录界面解决办法 2014年07月11日 10:50:10 阅读数:7931 redhat Linux一直用着好好地,今天打开只有图像界面背景,没有出现登陆界 ...
- 使用uni-app开发小程序,关于小程序更新后与用户本地不会及时更新解决办法
1.原因分析 在小程序更新开发版本之后,用户本地并没有对之前版本的小程序进行删除,那么再进入小程序的时候的版本是不会发生变化的,这是由于发版是异步执行,因此新版本将会覆盖的比较慢,本质是小程序的启动方 ...
- 【原】安装Win7和Ubuntu双系统后,Win7耳机无声音的解决办法
最近安装了Ubuntu的桌面版,作成了双系统,可是发现了一个问题:进入Win7后有时插耳机会没有声音,外放有声音.后来更新驱动也没有解决问题,最后在网上查到了解决办法. 产生原因:进入Ubuntu后, ...
- hadoop启动后jps查不到namenode的解决办法
最近由于项目需要开始接触hadoop,在配置伪分布式启动后,jps查询进程发现少了namenode,而DataNode却存在. 下面是我的core-site.xml和hdfs-site.xml配置: ...
- idea 导入项目后 有的项目目录结构不展开解决办法
如图:可能会出现这中国情况. 解决办法: 1.一般项目导入完成后,但是目录不展开, 2.出现这种情况一般情况下, 关闭idea close idea ,然后重新导入一遍就OK.
- PHP网站从Apache转移到Nginx后产生404错误的原因和解决办法
原案例分析: 1.原来的网站在wamp环境下搭建完成,一切正常,上传到虚拟主机环境为lnmp,结果访问时可以打开主页,然后点其他页面全部报404错误: 2.经分析得出原因:原网站环境为wamp使用了伪 ...
随机推荐
- ExtJS ComboBox 录入智能提示
ExtJS ComboBox非常复杂,有很多的属性:其中有的属性是针对某一种特定的方案而设计的,不是所有情况下都有效.我想下拉选择能支持录入,并且录入时能智能提示,弄了半天可以了,但是只能是mode= ...
- 为什么Domain controller上的time synchronization非常重要?
虚拟机默认情况下所拥有的资源都是不同的, 比如说CPU clock. 在一个忙碌的系统中, 虚拟机甚至可能在很短的一段时间内被拒绝分配资源给它, 这种情况还可能发生在高系统负荷, VMotion, B ...
- java学习笔记13--反射机制与动态代理
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...
- jsp button提交表单
表单提交可以用submit 也可以用button,下面介绍下面三种方式: 方法1 <form action = "提交的地址"> <input type=&quo ...
- .NET-MVC站点发布注意事项
在进行MVC站点发布的过程中需要注意bin文件,使用vs2013自带的发布功能容易漏掉一些dll文件,所以在发布之后需要将程序的bin目录下的文件拷贝到发布好的iis站点下面
- PHP中多IP段权限控制方案
在某些项目中我们可能会用到根据IP段进行权限校验,比如不在我们配置的IP段内的用户访问某些页面或功能模块时,将提示其权限不够并禁止访问该页面的内容.鉴于项目中需求各异,下面只说下大致思路以及我个人的实 ...
- 怎样更爽地看PDF杂志
下载了一些PDF的杂志,想着要是全屏双页显示,应该是很爽的,但是,下载了应该foxit reader,还是遇到一些问题: 1.全屏:F11即可 2.全屏后不双页:在选项中,"全屏" ...
- linux apache服务器优化建议整理(很实用)
转载:http://www.cnblogs.com/zhongbin/archive/2013/06/11/3131865.html 1.apache服务器的time_wait过多 fin_wait1 ...
- 使用js的indexOf,lastIndexOf,slice三函数轻易得到url的服务器,路径和页名
js的indexOf,lastIndexOf,slice能帮我们在js字符串处理时少走一些弯路. 程序如下: var url="http://www.cnblogs.com/xiandeda ...
- docker桥接
Ifconfig docker0 down Brctl delvr docker0 进入到网卡配置文件 修改eth0网卡参数 加入BIRDGE=br0 创建一个br0 其中ip为真实机的ip 更改do ...