Unity3D +Tolua 内存泄漏的问题以及查找过程

一、问题描述:

所做的游戏是一个大厅游戏,大厅内有很多款开发好的游戏,在每次打开一个游戏,内存就增加一些(在PC上测试,每打开一个游戏,内存大概会增加几十兆到一百兆左右),通过使用Unity中的Profiler查看到所增加的内训主要是图片资源没有释放的问题。

                            Unity3D +Tolua 内存泄漏的问题以及查找过程_第1张图片

图片中的资源在回到大厅之后,还是没有释放,导致Texture2D中所占的资源不能增加。

二、问题分析:

出现这个问题有四种可能:

1、C#的资源引用没有释放

2、toLua层的资源没有释放

3、C#没有及时的资源回收

4、Lua资源没有及时回收

三、查找问题过程

1、判断是不是因为C#或者lua的GC没有及时回收

测试方法:

①在大厅内增加一个测试按钮,回到大厅之后调用一下C#和lua的GC方法

注:

luaGC的方法:collectgarbage("collect")

C#GC的方法: GC.Collect();

C#GC原理:

 C#中和Java一样是一种系统自动回收释放资源的语言,在C#环境中通过 GC(Garbage Collect)进行系统资源回收,在数据基本类型中介绍到,C#数据类型分为引用类型和值类型,

值类型保存在Stack上,随着函数的执行作用域执行完毕而自动出栈,所以这一类型的资源不是GC所关心 对象。GC垃圾回收主要是是指保存在Heap上的资源。

 .NET的GC机制有这样两个问题:
  首先,GC并不是能释放所有的资源。它不能自动释放非托管资源。
  第二,GC并不是实时性的,这将会造成系统性能上的瓶颈和不确定性。

此外,GC并不是及时性的,这点要注意到,如果游戏中频繁的调用会出现游戏的卡顿问题,一般游戏会在切换场景中调用GC。

回归正题,点击GC回收按钮,通过查看Unity中的profiler,加载的资源并没有释放,可以确定并不是GC没有回收的问题。

2、判断是不是因为Tolua层的资源没有释放

Tolua和C#的交互是把所有的对象放在了ObjectTranslator.cs中,通过ObjectPool对C#对象进行存储,Lua层拿到的是一个int形式的Handler。

测试方法:

①新建两个Scene,使用项目使用的方法,加载一个prefabs,这个prefabs只放入一张图片资源,在通过Resource.Load找到这个Prefabs,加载到Scene中,切换另一个Scene,发现资源都已经被回收。说明不是在ObjectTranslator中的引用。

3、判断是不是因为C#或者lua的引用没有释放

①刚开始判断是否是因为lua的闭包导致的。如下面的例子

如果lua的对象引用到C#的对象,C#中又引用到lua中的方法:比如按钮的点击事件,lua方法注册给按钮,来监听状态改变的事件

self.button = obj:getCompent("Button")
self.button.onClick:AddListener(function()
	print("点击按钮")
end)

self -> Button -> OnClick -> luaFunction -> self 

分析一下:

  • self对button的引用是强引用,只要self不被lua回收,button就无法被c#回收
  • button对self也是强引用(通过onClick和匿名函数间接构成的),只要button不被c#回收,self就无法被lua回收

这个就造成了闭包的问题,如果不打断闭包,就会造成资源不能被回收。

回到正题,但是在lua脚本中,销毁时都会把所有的slef制为nil,不会出现闭包的情况,所以可以排除。

②判断是否是lua中封装的方法

这个是一个比较繁琐的事情,要一层层的去查看代码逻辑,是否有应用的资源没有被释放,但是通过最后的查找发现并不是在lua层的引用。

③判断是否是因为C#的引用导致的

这个过程也是需要一点点去排查逻辑代码,最后发现在C#中有一个方法是显示Panel,把所有加载prefabs,都放在一个Dictionary m_dALLGo中,退出的时候虽然有Destroy,但是在这个Dictionary中还是有引用,所以一直没有销毁。

终于找到问题最后只需要载调用销毁的地方调用

if (m_dALLGo.ContainsKey(panelName)
{
   m_dALLGo.Remove(panelName);
}

四、总结:

如果资源造成内存泄漏,可以先从自己写的代码逻辑去判断

  1. lua层是否出现闭包问题
  2. lua的逻辑是否有引用
  3. C#的逻辑是否有引用

 

 

你可能感兴趣的:(lua,C#,unity)