欢迎加入Unity业内qq交流群:956187480
qq扫描二维码加群,行业纵横颇多,每个人精通领域各异,旨在交流,
最近项目优化的太差了,里面内容比较多,经常启动后内存溢出导致闪退
常用资源加载的方法有三种:场景内预制资源,Resources内动态加载资源,AssetBundle外部资源
资源释放的方式 有二种:用过不再使用后立刻释放;在某一阶段统一释放不用的资源
1.场景内提前预制
静态就是资源直接放场景,静态资源无法立刻释放,但场景关闭由引擎统一释放。但静态过于死板,除了整个场景生命周期中必须使用的资源外,不建议静态加载,为什么,消耗时间,占用内存;比如说,游戏场景持续使用的背景音乐,那么静态的确是最佳选择;但如果场景的开场要播放一个5M的音乐后面不再使用,这个资源用静态就是白白增加了5M音乐的加载时间和浪费了5M内存,得不偿失。静态资源的加载策略是: 只加载必要固定的资源,或者极其微小损耗不大的资源。释放策略是:由引擎负责。
2.Resources动态加载资源
Resources的资源一般和游戏一起打包,一般是游戏内使用的关键资源。Resources主要加载一些动态的或者需要灵活处理的资源。加载的办法是先Reources.Load,然后GameObject.Instantiate,立刻释放的办法是Reources.UnloadAsset,统一释放的办法是Resources.UnloadUnusedAssets。在用UnloadAsset()去释放GameObject的时候会报错:UnloadAsset may only be used on individual assets and can not be used on GameObject's/Components or AssetBundles。也就是说不能释放除individual assets类型以外的资源类型,只能释放(mesh / texture / material / shader )。如果想要释放不用的gameObject就用UnloadUnusedAssets(),在调用之前需要把对象设置为null。另外还有一点需要注意这个UnloadAsset释放的对象是通过Resources加载出来的资源。
Resources的主要优点是使用灵活,缺点是开发复杂;加载的时候注意一个资源只需要Reources.Load一次,管理好Load出来资源的引用,尽量不要用静态引用,给释放制造困难。UnloadUnusedAssets前必须注意释放所有引用,所有Instantiate出来的对象必须销毁。
Resources的加载释放策略是: 只加载必须使用的资源,加载以后如果无需重复使用,或者使用频率非常的低,应该在明确使用完毕以后(如图片显示结束,音乐播放完毕)立刻用Reources.UnloadAsset释放。对于后续仍然会反复采用的资源,建议在内存中缓存引用,以防止后续加载不再反复调用Load函数,场景关闭前释放缓存,销毁所有实例化对象,等待Resources.UnloadUnusedAssets统一释放。UnloadUnusedAssets释放建议在当前场景完全销毁以后,再后续场景中执行最为稳妥。
3.AssetBundle外部资源
AssetBundle资源的机制基本和Resources类似,但可以独立打包,支持网络下载和文件读取,一般是游戏中使用的辅助资源。
AssetBundle机制要比Resources多一步,首先要通过AssetBundle.LoadFromXXX把AssetBundle加载到内存,然后使用AssetBundle.LoadAsset加载资源,最后GameObject.Instantiate为实例化对象。所以一个完整实例化的 AssetBundle存在三处内存引用,在释放策略上相对复杂。
AssetBundle的释放功能主要通过AssetBundle.Unload,而且也可以使用Reources.UnloadAsset和Resources.UnloadUnusedAssets进行释放。
AssetBundle的加载释放策略分两种情况:
a.加载完毕以后不再需要使用的资源包,可以再加载完毕以后立刻调用AssetBundle.Unload(false)释放资源包内存,而在此基础上,对于AssetBundle.LoadAsset以后并不再使用的资源,可以通过Reources.UnloadAsset释放,如需持续使用,也可能等待Resources.UnloadUnusedAssets后续统一释放。
b.加载完毕以后仍需持续使用的资源包,则必须保留AssetBundle引用,这种方式下,比较建议的方式是在场景完全销毁以后,一次性调用AssetBundle.Unload(true)完全释放改资源包和其所有加载资源。
1.场景内提前预制
运行后可以看到镜像文件里没有,但是在Assets里面存在一个Cube,Scene里存在一个Cube
运行状态下分别执行 Destory()和Resources.UnloadAsset(),执行Desotry确实是可以把场景内资源释放掉。
2.Resources动态加载资源
中间可能会有报错:Instantiating a non-readable 'Girl' texture is not allowed! Please mark the texture readable in the inspector or don't instantiate it.
public Object o;
public GameObject go;
private void Start()
{
o = Resources.Load("Girl") ;
go = Instantiate(o) as GameObject;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.U))
{
Resources.UnloadAsset(o);
Debug.Log("释放成功");
}
}
3.AssetBundle外部资源
private void LoadBundle()
{
string assetBundlePath = Application.streamingAssetsPath + "/cube.assetbundle";
byte[] s = File.ReadAllBytes(assetBundlePath);
var a = AssetBundle.LoadFromMemory(s);//a加载到内存
var b = a.LoadAsset("Cube");//b加载内存的资源
c = Instantiate(b);//c实例化对象
Debug.LogError("LoadAssetBundle over!");
}
释放:加载完直接释放的资源
var a = AssetBundle.LoadFromMemory(s);//a加载到内存
var b = a.LoadAsset
c = Instantiate(b);//c实例化对象
a.Unload(false);//加载完毕以后不再需要使用的资源包直接释放
---------------------------------------------------------------
UnloadUnusedAssets释放后assets内资源释放,destory()场景实例
欢迎加入Unity业内qq交流群:956187480
qq扫描二维码加群,行业纵横颇多,每个人精通领域各异,旨在交流,