1. static关键字

使用到static关键字的地方需格外注意,避免内存不能unload,先看测试结果

实例是否为static 成员变量是否为static Resources.UnloadUnusedAssets()前是否置空static实例 Resources.UnloadUnusedAssets()前是否置空成员变量 成员变量所引用资源是否被回收
/
/
/ 不能
/
不能
不能
不能
  • 静态实例所持有的静态/非静态成员变量都需要及时置空,或者直接置空该静态实例
  • 非静态实例所持有的静态成员变量需要及时置空
    instance不一定是置空操作,指向别的实例也可以,即instance = new InstanceClass()

2.远程下载Texture

从远程下载一张贴图Texture,并赋值给Image _img,这也是新手常会忽略的会导致内存溢出的情况。彻底的unload内存的流程应该是这样的:

  1. 以下三选一都能使Image与Texture之间的引用断开,可根据业务需求选择
    • Destroy_img所在gameObject 即 Destroy(_img.gameObject)
    • Destroy_img组件即Destroy(_img)
    • 将_img.sprite置空,即_img.sprite = null
  2. 将引用到Image的变量置空,即_img = null
  3. 当然如果对Texture缓存或者对由Texture转换所得的Sprite进行缓存了,还需对这些缓存引用置空,即 _tempSprite = null 或 _texDict.Clear() 或 _texDict = null
  4. 以上步骤任意顺序执行完后再调用Resources.UnloadunusedAsset()即可将Texture从内存彻底卸载

附上测试代码:

private Image _img;
private Dictionary<string, Texture> _spriteDict;
private Sprite _tempSprite;
private void Start()
    var texture = GetTextureFromWeb(url);
    _spriteDict.Add("texName",texture);  
    _tempSprite = Util.Texture2Sprite(texture ); 
    _img = _tempSprite;
private void Update()
    if (Input.GetMouseButtonDown(1))
        _img = null;
        _spriteDict.Clear();//或者 _spriteDict = null;
        _tempSprite = null;
        Resources.UnloadUnusedAssets();

3.Resources&Instantiate Gameobject

调用Resources.Load得到original之后,再实例化(Instantiate)得到instance。
先说unload original的内存,调用Resources.UnloadunusedAsset()就能将original从内存彻底unload
,当然如果有变量引用这original,在调用Resources.UnloadunusedAsset()前,需对这些引用置空

private GameObject _cubeOriginal;
private GameObject _cubeInsatnce;
 private void Start()
     _cubeOriginal = Resources.Load<GameObject>("Cube");
     _cubeInsatnce = Instantiate(_cubeOriginal, transform);
private void Update()
    if (Input.GetMouseButtonDown(1))
        _cubeOriginal = null;
        Resources.UnloadUnusedAssets();

所以如果original不能复用的情况下,建议将original定义为局部变量,使其作用域在Start()内,这种写法更简洁。在unload original的内存时,直接调用Resources.UnloadUnusedAssets()即可

private GameObject _cubeInsatnce;
 private void Start()
      var cubeOriginal = Resources.Load<GameObject>("Cube");
     _cubeInsatnce = Instantiate(cubeOriginal , transform);
private void Update()
    if (Input.GetMouseButtonDown(1))
        Resources.UnloadUnusedAssets();

这一点就比较有意思了,无需Destroy instance即可 unload original,这说明 Instantiate后得到的instance 对original不存在"引用依赖"关系,这种微妙的关系这里做了解释。

以上是unload original的内存 ,接下来是unload instance的。

这一部分内存,只需要Destroy(instance.gameObject),对引用到instance的变量置空
最后在调用Resources.UnloadUnusedAssets()即可将unload instance

4.场景中原来存在的Gameobject与Resources Instantiate 得到的Gameobject

这两者的内存unload还是还一些差别的。

前者举个实例来说:场景中原来存在一个Cube,Destroy(cube)后调用Resources.UnloadUnusedAssets()虽能unload Cube的内存,但却不能unload Cube所引用到的资源,所以还需要对Cube所引用资源置空,即对material置空,这样才能从彻底unload Cube

transform.Find("Cube").GetComponent<MeshRenderer>().material = null;
Destroy(transform.Find("Cube").gameObject);
Resources.UnloadUnusedAssets();

PS:笔者在测试期间,发现一个奇怪的现象,如果场景中的Cube是一个预制体,并未Unpack Prefab Completely,material那部分的内存即使是按照以上步骤执行还是无法unload的(Unity版本: 2018.4.01f,环境:PC),如知道原因请及时与我联系。

后者要卸载内存则少了对所引用到的资源置空的步骤,即

private void Start()
    Instantiate(Resources.Load<GameObject>("Cube"), transform);    
private void Update()
    if (Input.GetMouseButtonDown(1))
        Destroy(transform.Find("Cube(Clone)").gameObject);
        Resources.UnloadUnusedAssets();

5.Resources.UnloadAsset

Texture2D可以通过该API卸载,但是TextAsset并不能
在这里插入图片描述

Unity内存的管理并不是简单的事情,稍不注意就会导致内存泄漏。文中如果有错误,请及时与我联系~

Obscured Items是一组类型,旨在隐藏在Unity游戏引擎使用类似于Cheat Engine的内存扫描器,用来预防unity开发的游戏防止内存作弊。 支持的类型包括:bool、byte、sbyte、char、short、ushort、int、uint、long、ulong、double和float。
内存优化之内存溢出 Out of Memory 导致的崩溃为什么导致内存溢出?Unity内存管理系统堆栈内存和堆内存什么是托管堆?申请内存的原理造成内存溢出的原因解决内存溢出的方案 为什么导致内存溢出? 导致内存溢出的原因很简单,就是因为我们在大量的使用内存,而由于系统(OS)各种限制原因,我们可以申请使用的内存已达上限,没有多余的内存空间进行申请使用,但是我们仍在无节制的使用内存,最后就导致我们使用的内存已经超过了可使用的内存上限。从而就造成了 Out of Memory 内存溢出,甚至产生崩溃。 2.Resources.UnloadUnusedAssets卸载所有没有引用的资源 3.Resources.UnloadAsset卸载单个资源,只能卸载单个基础资源(如Texture,Sprite),不能卸载GameObject。 4.Resources.UnloadAsset卸载,Sprite只卸载Sprite组件,和Texture2D关联,不卸载Texture2D图片,需要在调用Resources.UnloadUnusedAsset
**Unity 3D - renderTexture导致内存泄露 : ** Unity2019.1官方文档上写明,renderTexture不被GC,所以意味着如果创建的renderTexture不去管理的话,内存占用越来越大。 经过多次测试创建和回收,得出结论: 1.实例化new出来的对象, 调用Release方法不立即释放, 切换场景也不释放。 从下面两张图看得出,创建后内存和o...
Unity3d GameObject.Instantiate函数理解Instantiate函数是unity3d进行实例化的函数,也就是对一个对象进行复制操作的函数,这个函数共有五个重载(overloaded)函数,对这五个函数的理解不清楚的话产生的效果也不相同,现在对这五个函数做一定的理解。先附上unity3d API 对这个函数的描述: Instantiate函数实例化是将origina
Unity几种动态加载Prefab方式的差异: 其实存在3种加载prefab的方式: 一是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate 二是Resource.Load Resources的缺点:1.与显示Inspector上直接引用相比,Resources使用不方便.     2.不管你Resources上的资源是否调用了,当你发布的时候,Resources上的资源全部一起打包掉,无法作更新. Resources里的方法: Resources.Load :动态加载特殊文件夹Resources里的文件.
1.最近的项目,在修改公司之前的项目将其打出Webgl后发现内存溢出了,但是在Editor里没有这个现象,继续在Editor里,发现果然这个项目内存越占越多,如下图所示: 2.打开Unity的Profiler,选择Memory,运行项目,果然此项目一直在创建Texture,如下图所示。 3.找了一儿,发现是点击翻页按钮时,占用的内存一直在增加,于是查看这个按钮的代码,果然发现了问题,方法里...