前言

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

问题

从大厅进到单局的过程中,会经过选择英雄和加载两个流程,这两个流程对应的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. 切线空间(Tangent Space)法线映射(Normal Mapping)【转】

    // 请注明出处:http://blog.csdn.net/BonChoix,谢谢~) 切线空间(Tangent Space) 切换空间,同局部空间.世界空间等一样,是3D图形学中众多的坐标系之一.切 ...

  2. TensorFlow进阶(四)---名称域和共享变量

    变量作用域 tensorflow提供了变量作用域和共享变量这样的概念,有几个重要的作用. 让模型代码更加清晰,作用分明 变量作用域域 通过tf.variable_scope(<scope_nam ...

  3. MapReduce中的分布式缓存使用

    MapReduce中的分布式缓存使用 @(Hadoop) 简介 DistributedCache是Hadoop为MapReduce框架提供的一种分布式缓存机制,它会将需要缓存的文件分发到各个执行任务的 ...

  4. 小课堂week17 编程范式巡礼第二季 并发那些事

    编程范式巡礼第二季 并发那些事 继续上周的编程范式话题,今天想聊一下并发范式. 并发也算一种范式? 真正的并发式编程,绝不只是调用线程API或使用synchronized.lock之类的关键字那么简单 ...

  5. IIs 中运行asp程序出现“An error occurred on the server when processing the URL. Please contact the system administrator.”错误

    在个人的win08系统上使用IIs运行 asp程序结果出现了以下错误 An error occurred on the server when processing the URL. Please c ...

  6. FrameWork模型中引入宏函数报错解决方法

    如下图在Framework的一个简单维度中加入宏函数 解决办法如下图 step1: step2: PS :Cognos 10.1.1中 在cognos connection中创建数据源,为什么没有od ...

  7. import MySQLdb UserWarning

    Finished processing dependencies for MySQL-python==1.2.5 ╭─haoke@haokedeMBP ~/ProgramFiles/MySQL-pyt ...

  8. 使用nmonchart把.nmon文件转换成html

    转载:https://blog.csdn.net/zd470015321/article/details/68923280 我的环境 :centos6.6 下载地址 nmon: http://nmon ...

  9. (笔试题)关于C++的虚函数和多态性

    以下两段程序的输出是什么? 程序1: #include "stdio.h" class Base { public: int Bar(char x) { return (int)( ...

  10. 【树莓派】-bash: /usr/local/java/jdk1.8.0_161/bin/java: cannot execute binary file: Exec format error

    遇到这样的问题:-bash: /usr/local/java/jdk1.8.0_161/bin/java: cannot execute binary file: Exec format error ...