原创文章如需转载请注明:转载自风宇冲Unity3D教程学院

                       
                       U3D内存优化
 
读了Hog关于内存管理文章, 自己测试了下。
有以下收获:
(1)Unity的Profiler性能监测是非常准确。
(2)测试复盘的 结果也完全与Hog的一致
 
(3)但是场景里已经放的物体,删除后,GameObject,Transform等复制出来的是被删掉了.但是引用的贴图却没有被删除。使用Resources.UnloadUnusedAssets并没有效果. 
或者实时创建的,依然没有被释放。
 
最后用了Resources.UnloadAsset(t2d);才得到释放。
(4)Resources.UnloadUnusedAssets(); 释放的资源并不一定是 Resources文件夹下的,内存里有的都算。
 
(5)有人说删除总是会被延迟到当前帧的末尾:所以需要这样
  1. IEnumeratorOnLevelWasLoaded(int level)
  2. {
  3. Destroy(gameObject);
  4. yield return null;
  5. Resources.UnloadUnusedAssets();
  6. }
 
但实测发现上并不如此,无论是Destroy(obj); 还是DestroyImmediate(obj); 之后立刻调用Resources.UnloadUnusedAssets();都会被释放。
 
(6)删除

DestroyImmediate(obj);

t2d = null;

mat=null;

Resources.UnloadUnusedAssets(); 
 
t2d是reference到UIAtlas这张贴图,属于direct reference。 而mat这个材质上的mainTexture是reference到UIAtlas,所以mat是indirect reference。 而不管是direct reference 还是indirect reference都必须为null,即t2d及mat都必须为null, 否则UnloadUnusedAssets就不起作用。
 
所以在Inspector里指定的,有reference,一运行就会自动加载该资源。
 
(7)Resources.UnloadAsset(t2d);
当使用Resources.UnloadAsset后,若依然有物体用该图,那么物体就变全黑
 
(8)
 
可以Destroy引用
 
  1. using UnityEngine;
  2. using System.Collections;
  3. public class MyTest : MonoBehaviour {
  4. private GameObject obj;
  5. void OnGUI()
  6. {
  7. if(GUI.Button(new Rect(0,0,100,50),"Create"))
  8. {
  9. GameObject tmpPrefab =  Resources.Load("myTestPlayer") as GameObject;
  10. obj = Instantiate(tmpPrefab) as GameObject;
  11. Instantiate(tmpPrefab);
  12. }
  13. if(GUI.Button(new Rect(0,50,100,50),"Delete"))
  14. {
  15. Destroy(obj);
  16. Resources.UnloadUnusedAssets();
  17. }
  18. }
  19. }

也可以自己删自己

  1. using UnityEngine;
  2. using System.Collections;
  3. public class DeleteSelf : MonoBehaviour {
  4. void Start () {
  5. Destroy(gameObject,3f);
  6. }
  7. }

不光是开始的时候,任何时候加载 物体,里面有引用的话。都会载入都内存里。

结论
资源加载分为静态加载和动态加载,
静态加载: 场景中静态物体加载
动态加载: 
(1)public GameObject指向prefab,
(2)Resources.Load, 
(3)Assetbundle
其中(1)(2)都是在Instantiate的时候才加载贴图等资源,所以容易在创建物体时有卡顿现象,解决办法是预先Instantiate然后隐藏。(3)是在Assetbundle.Load的时候就加载贴图等资源了,Instantiate时仅仅时clone,所以不会在创建物体时出现卡顿现象。
 
不建议使用public GameObject指向prefab。小型游戏可以直接使用Resources.Load然后预创建的方式。大型游戏特别是网游建议全部用Assetbundle。但是Assetbundle是不适合快速迭代开发的。个人觉得可行的思路是先快速迭代开发原型,等原型及核心玩法接受实际去玩的验证并通过后,再使用Assetbundle并采用 模块->拼接的方法进行开发。
 
Application.LoadLevel是会自动释放上一个场景所占用的内存的,包括动态创建的物体(但是不包括AssetBundle文件自身的内存镜像,那个必须要用Unload来释放,用.net的术语,这种数据缓存是非托管的。)。因此短时间的场景或者 场景里内存在初进场景后增加幅度不大的时候,都可以采用场景切换来自动释放内存的。而面对在一个场景里,内存有增加,或者说不断增加各种物体的话。那么就需要Resources.UnloadUnusedAssets。ab的话,则是AssetBundle.Unload
AssetBundle.Unload(flase)是释放AssetBundle文件本身的内存镜像,不包含Load创建的Asset内存对象。
AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。
 
Reference:

U3D内存优化的更多相关文章

  1. U3D DrawCall优化手记

    在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这些问题在最后,恐怕只能通过一次彻底的重构来解决 现在的游戏跑起来会有接近130-170个左右的Dra ...

  2. 【转】 U3D DrawCall优化手记 - 夜阑卧听风吹雨

     原文  http://www.cnblogs.com/ybgame/p/3588795.html 在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这 ...

  3. (转)U3D DrawCall优化手记

    自:http://www.cnblogs.com/ybgame/p/3588795.html 在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这些问题 ...

  4. In-Memory:内存优化表的事务处理

    内存优化表(Memory-Optimized Table,简称MOT)使用乐观策略(optimistic approach)实现事务的并发控制,在读取MOT时,使用多行版本化(Multi-Row ve ...

  5. 试试SQLSERVER2014的内存优化表

    试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...

  6. In-Memory:内存优化表 DMV

    在内存优化表的DMV中,有两个对象ID(Object ID): xtp_object_id 是内部的内存优化表(Internal Memory-Optimized Table)的ID,在对象的整个生命 ...

  7. android内存优化

    背景 虽然android设备的配置越来越高,但是,由于android系统的机制导致(最主要是app程序的主线程不会真正退出而是在后台常驻内存中) ,这样手机中安装过多的app之后,导致内存被大量占用, ...

  8. JavaScript内存优化

    JavaScript内存优化 相对C/C++ 而言,我们所用的JavaScript 在内存这一方面的处理已经让我们在开发中更注重业务逻辑的编写.但是随着业务的不断复杂化,单页面应用.移动HTML5 应 ...

  9. [WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化

    11.2.4 大数据量网络图片列表的异步加载和内存优化 虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性.对于虚拟化的技术,我们不仅仅只是依 ...

随机推荐

  1. Java学习笔记()ArrayList

    1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...

  2. Eolinker——高级代码模式(JS语法)

    ### 定义遍历与赋值JavaScript 使用关键字 var 来定义变量, 使用等号来为变量赋值:```var a=1;<!--or-->var a;a=1 ``` ### 输出输出函数 ...

  3. 第七章 用户输入和while语句

    大多数编程都旨在解决最终用户的问题,为此通常需要从用户那里获取一些信息.例如,假设有人要判断自己是否到了投票的年龄,要编写回答这个问题的程序,就需要知道用户的年龄,这样才能给出答案.因此,这种程序需要 ...

  4. linux中忘记root密码解决方案

    方法一: 如果用户具有sudo权限,那么直接可以运行如下命令: #sudo su root #passwd #更改密码 或者直接运行sudo passwd root命令就可以直接更改root密码. 有 ...

  5. vue中methods、watch、computed之间的差别对比以及适用场景

    首先要说,methods,watch和computed都是以函数为基础的,但各自却都不同: 一.computer 当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性. <p id=& ...

  6. 一道关于数据库(经典父子级 ID 关联)更新题,大家帮忙想想还有其它解决思路没有?

    昨天,一同事发过来的一道数据库题目,就是哪种经典的父子级 ID 在同一数据库表中设计类型.需要在原表中添加一个字段,同时,将该节点的父子级详细信息插入到原表新增的一字段中,具体效果如下图. AreaC ...

  7. C# 6.0 新特性 (一)

    概述 尽管 C# 6.0 尚未完成,但现在这些功能正处于接近完成的关键时刻.自 2014 年 5 月发布文章“C# 6.0 语言预览版”(msdn.microsoft.com/magazine/dn6 ...

  8. 【转】使用 python IDLE 自带的 debuger 进行调试

    IDLE自带了调试器(虽然不怎么使吧). 关于如何在 IDLE 中进行调试网上的教程讲的很模糊,于是自己整理了一下,和大家分享~ 第一步:打开python shell,并在shell中打开debuge ...

  9. 爱奇艺全国高校算法大赛初赛A

    $01$背包. 数据范围:物品个数小于等于$3000$,背包大小小于等于$1000000$. $map<int,long long>dp$,用$map$去做$dp$,可以少遍历很多状态,可 ...

  10. libevent的作用或者说是有哪些功能

    1. 介绍 libevent是一个用来开发可扩展的网络服务器的事件通知函数库.当一个文件描述符上的特定事件发生或是一个超时时间到达后,libevent API提供一种执行回调函数的机制.而且,libe ...