Unity4.x AssetBundle内存管理 依赖打包逻辑 全套

1.依赖打包,先获取依赖关系

先获取所有依赖关系。并且存储在XML文件中,因为我们的项目只需要打包Prefab,所以只需要一维的依赖就够用了

xml version="1.0" encoding="UTF-8"?>
<root>
  <resource AssetBundleName="cc5f40250fc1dad43a33c9b9b31001dd" AssetName="yujing_yuan_30" UnityType="UnityEngine.GameObject">
    <child AssetBundleName="38d758a33f8f4a147be81f1f80e647b4" AssetName="glow_00143" UnityType="UnityEngine.Material" />
    <child AssetBundleName="ad78e334b10df0a4ea65f9ac040ee59a" AssetName="glow_00143" UnityType="UnityEngine.Texture2D" />
    <child AssetBundleName="90642d347cb46c942a94cf1bbeba3aba" AssetName="glow_00175" UnityType="UnityEngine.Texture2D" />
    <child AssetBundleName="889af9f557af4954a8271e4bd47669e6" AssetName="glow_00141" UnityType="UnityEngine.Material" />
    <child AssetBundleName="c5b912f87af58c44789a0e72b9cb5716" AssetName="glow_00175" UnityType="UnityEngine.Material" />
    <child AssetBundleName="abffe21d6aa8bd644ab62736766b4d1e" AssetName="glow_00141" UnityType="UnityEngine.Texture2D" />
    <child AssetBundleName="8ee952aebc51efe42ad48cbc1fb60ae8" AssetName="glow_00175_3" UnityType="UnityEngine.Material" />
  </resource>

AssetBundleName=GUID;

2. 开始打Assetbundle包

// 按顺序打包,1,font,2 sound,3 Texture,4.mat 5.fbx 其余的不管。prefab自动打包
List<EditorAssetConfig> texture2dList = new List<EditorAssetConfig>();
List<EditorAssetConfig> shaderList = new List<EditorAssetConfig>();
List<EditorAssetConfig> materialList = new List<EditorAssetConfig>();
List<EditorAssetConfig> otherList = new List<EditorAssetConfig>();
List<EditorAssetConfig> gameObjectList = new List<EditorAssetConfig>();
List<EditorAssetConfig> fontList = new List<EditorAssetConfig>();
List<EditorAssetConfig> audioClipList = new List<EditorAssetConfig>();
List<EditorAssetConfig> prefabtList = new List<EditorAssetConfig>();


EditorAssetConfig是一个结构体 

public class EditorAssetConfig
{
    // assetName =  guid 形成好的
    public string AssetBundleName;

    // 资源类型
    public string objType;

    // 资源类型
    public string AssetPath;

    // sourcesName
    public string AssetName;

    // 是否是prefab
    public bool isPrefab = false;

    // 被引用的计数
    public int dependenciesCount = 0;

    // 下级(只有一维)因为只打包prefab
    public List<EditorAssetConfig> child = new List<EditorAssetConfig> ();
}

BuildPipeline.PushAssetDependencies ();

// ===============

     上面的子Asset先打包List循环打包

=================//


// ===============

BuildPipeline.PushAssetDependencies ();

打包Prefab

BuildPipeline.PopAssetDependencies();

================//

            
BuildPipeline.PopAssetDependencies();


// 注意事项,打出来的assetbundleName是 GUID生成的。运行过程中需要GUID来获取ab文件,所以打包过程中,需要把GUID对应原文件的名字记录下来。保存在xml中,相当于Unity5.x里德Mainfest 一样

xml version="1.0" encoding="UTF-8"?>
<root>
  <resource AssetBundleName="cc5f40250fc1dad43a33c9b9b31001dd" AssetPath="Assets/ABResources/AllEffects/yujing_yuan_30.prefab" />
  <resource AssetBundleName="38d758a33f8f4a147be81f1f80e647b4" AssetPath="Assets/Effects/Textures/Materials/glow_00143.mat" />
  <resource AssetBundleName="ad78e334b10df0a4ea65f9ac040ee59a" AssetPath="Assets/Effects/Textures/glow_00143.png" />

// 打出来很多散的文件,

https://img-blog.csdn.net/20160919103408492

Unity4.x AssetBundle内存管理 依赖打包逻辑 全套_第1张图片Unity4.x AssetBundle内存管理 依赖打包逻辑 全套_第2张图片


// 我们项目比较大,热更新上万个assetbundle io的操作太多。所以要合并文件

合并assetbundle的原理:

比如每30个assetbundle做成一个package

1.获取30个文件的byte

2.写入新的package.bytes文件里

3.这里需要一个头文件,表示记录了每一个assetbundle在这个package里的startIndex,跟EndIndex


=======================================================================================================

   游戏运行过程中读取assetbundle

1.先下载package  。 根据自己记录MD5值验证是否更新package

2.下载package以后先解压。上面描述过。package的2进制头文件里写了一些描述,用来解压package用的

根据startIndex跟EndIndex 值 获取相应的单个Assetbundl文件,比如


// 解析头文件

        MemoryStream stream = new MemoryStream (bytes);
        long headLength = long.Parse (headLength(头文件长度));
        stream.Position = stream.Length - headLength;
        byte[] strBytes = new byte[headLength];
        stream.Read (strBytes, 0, strBytes.Length);
        string str = System.Text.UTF8Encoding.Default.GetString (strBytes);
        // 字符串解析
        string[] strArr = str.Split (';');
        for (int i = 0; i < strArr.Length; i++) {
            string _assetStr = strArr [i];
            
            AssetBundlesInfo info = new AssetBundlesInfo ();
            
            string[] assetInfo = _assetStr.Split ('|');
            
            if (assetInfo.Length > 1) {
                info.abName = assetInfo [0];
                
                info.sindex = assetInfo [1];
                
                info.length = assetInfo [2];
                

//解析完头文件内容自己定义一个结构里保存起来
                package.childAssets.Add (info);
            }
        }
   

最后根据这个配置信息从package里扣出来每一个assetbundle文件,并且保存在缓存目录中

Unity4.x AssetBundle内存管理 依赖打包逻辑 全套_第3张图片

======================================= 热更新部分到这里 ==========================================================


======================================= 下面是内存管理 ==========================================================

加载一个assetbundle 以后会生成两个内存

AssetBundl m_assetBundle = www.bundle;

UnityEngine.Object m_Obj = www.bundle.MainAsset;

1是压缩的文件2.assetbundl.mainAsset获取的实例化的文件=你要Instance的prefab文件

我们加载一个内存以后习惯用Assetbunld.unload(false);

调用unload(false)以后assetbundle这个对象编程Null

但是m_Obj这个变量没有被释放,这个变量在内存管理中很重要

我们打包的是依赖关系。假设一个文理。被多个Object引用。那么这个m_Obj的refcount 引用计数会有N多个

当m_Obj的refcount 引用计数为0 的时候调用Resources.UnloadUnusedAssets(); 才能真正的从内存中移除

依赖关系的内存很复杂。假设有两个prefab  A跟B 都依赖C这个文理

加载资源C,在加载A 实例化一个完整的A.prefab

然后立马释放掉 

C.assetbundle.unload(false)

A.assetbundle.unload(false)

此事 C.assetbundl ,A.assetbundl 都变成空了。但是!

C.m_Obj, A.m_Obj 这两个Obj内存还存在。

这时候在加载B.prefab

由于B也依赖C资源所以先加载C资源

if(null != C.m_Obj)  说明这个依赖资源还在内存当中就不需要重新www.load了

直接加载 www.load(B)


从C#内存管理角度来说 C.m_Obj 什么时候会被释放掉呢?

Destroy(A)

Destroy(B)

按理说这时候C的引用计数变成0了。就可以释放掉了。


结果!C的引用计数还是1. 那是因为你自己写的类里面存储了这个对象类似

C.m_Obj = C的资源内存地址 这时候你自己的类引用了一个+1

那么C 不会被释放掉。


解决方法:

我们自己写的类里 不能直接“=”来引用

System.WeakReference 这个类是弱引用,C#的

m_Obj = new System.WeakReference (obj);

需要这么赋值,这时候C资源的内存管理完全由 系统来控制,当系统发现A,跟B都销毁了以后C的引用计数就变成0

这时候你在打印 m_Obj 

Debug.Log(m_obj); ======Null







你可能感兴趣的:(u3d)