U3D内存优化
2024-09-21 06:09:50
原创文章如需转载请注明:转载自风宇冲Unity3D教程学院
U3D内存优化
读了Hog关于内存管理文章, 自己测试了下。
有以下收获:
(1)Unity的Profiler性能监测是非常准确。
(2)测试复盘的 结果也完全与Hog的一致
(3)但是场景里已经放的物体,删除后,GameObject,Transform等复制出来的是被删掉了.但是引用的贴图却没有被删除。使用Resources.UnloadUnusedAssets并没有效果.
或者实时创建的,依然没有被释放。
最后用了Resources.UnloadAsset(t2d);才得到释放。
(4)Resources.UnloadUnusedAssets(); 释放的资源并不一定是 Resources文件夹下的,内存里有的都算。
(5)有人说删除总是会被延迟到当前帧的末尾:所以需要这样
- IEnumeratorOnLevelWasLoaded(int level)
- {
- Destroy(gameObject);
- yield return null;
- Resources.UnloadUnusedAssets();
- }
但实测发现上并不如此,无论是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引用
- using UnityEngine;
- using System.Collections;
- public class MyTest : MonoBehaviour {
- private GameObject obj;
- void OnGUI()
- {
- if(GUI.Button(new Rect(0,0,100,50),"Create"))
- {
- GameObject tmpPrefab = Resources.Load("myTestPlayer") as GameObject;
- obj = Instantiate(tmpPrefab) as GameObject;
- Instantiate(tmpPrefab);
- }
- if(GUI.Button(new Rect(0,50,100,50),"Delete"))
- {
- Destroy(obj);
- Resources.UnloadUnusedAssets();
- }
- }
- }
也可以自己删自己
- using UnityEngine;
- using System.Collections;
- public class DeleteSelf : MonoBehaviour {
- void Start () {
- Destroy(gameObject,3f);
- }
- }
不光是开始的时候,任何时候加载 物体,里面有引用的话。都会载入都内存里。
结论
资源加载分为静态加载和动态加载,
静态加载: 场景中静态物体加载
动态加载:
(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内存对象。
AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。
Reference:
最新文章
- Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!
- UVA 11404 Palindromic Subsequence[DP LCS 打印]
- Liferay 6.2 改造系列之五:修改默认站点的页面内容
- Sublime Text 设置文件详解
- 160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘
- web设计经验<;二>;设计华丽的用户体验的6个热门技巧
- javascript异步执行函数导致的变量变化问题解决思路
- [BZOJ 3791] 作业 【DP】
- [原创]旧事重提:只配置参数实现OAuth2登录
- PoolManager 简单使用
- 获取MySql每一列的数据类型和长度默认值等信息
- Mysql 测试题
- sybase central 报 NullPointerException 解决
- struts2框架之自定义拦截器和配置
- bitcoin PoW原理及区块创建过程
- python笔记26-命令行传参sys.argv实际运用
- Python3 re模块正则表达式中的re.S
- 常用EL函数汇总 fn:contains ,fn:substring,fn:substringAfter...
- react 设置代理(proxy) 实现跨域请求
- 补习知识:Entity Framework Code First属性映射约定