U3D内存优化

读了Hog关于内存管理文章, 自己测试了下。

有以下收获:

(1)Unity的Profiler性能监测是非常准确。

(2)测试复盘的 结果也完全与Hog的一致

(3)但是场景里已经放的物体,删除后,GameObject,Transform等复制出来的是被删掉了.但是引用的贴图却没有被删除。使用Resources.UnloadUnusedAssets并没有效果. 

或者实时创建的,依然没有被释放。

最后用了Resources.UnloadAsset(t2d);才得到释放。

(4)Resources.UnloadUnusedAssets(); 释放的资源并不一定是 Resources文件夹下的,内存里有的都算。

(5)有人说删除总是会被延迟到当前帧的末尾:所以需要这样

  1. IEnumerator OnLevelWasLoaded(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.  
  4. public class MyTest : MonoBehaviour {
  5. private GameObject obj;
  6. void OnGUI()
  7. {
  8. if(GUI.Button(new Rect(0,0,100,50),"Create"))
  9. {
  10. GameObject tmpPrefab =  Resources.Load("myTestPlayer") as GameObject;
  11. obj = Instantiate(tmpPrefab) as GameObject;
  12. Instantiate(tmpPrefab);
  13. }
  14. if(GUI.Button(new Rect(0,50,100,50),"Delete"))
  15. {
  16. Destroy(obj);
  17. Resources.UnloadUnusedAssets();
  18. }
  19. }
  20. }

也可以自己删自己

 

 

 

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

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

 

结论

资源加载分为静态加载和动态加载,

静态加载: 场景中静态物体加载

动态加载: 

(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内存对象。

猜你喜欢

转载自blog.csdn.net/alone_ws/article/details/85127613