• U3D内存优化


    原创文章如需转载请注明:转载自风宇冲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:
  • 相关阅读:
    「USACO 2020 US Open Platinum」Exercise
    Equilateral Triangles
    [USACO 2020 February Platinum]Help Yourself
    「ICPC World Finals 2019」美丽的桥梁
    「ICPC World Finals 2019 何以伊名始
    COCI20162017 Contest#6 F
    COCI2016/2017 Contest#3 F Meksikanac
    TopCoder SRM 570 Div1 CurvyonRails
    COCI2016-2017 Contest#2 F
    UOJ Round Good Bye JiHai D. 新年的追逐战
  • 原文地址:https://www.cnblogs.com/lancidie/p/5860766.html
Copyright © 2020-2023  润新知