unity资源释放(AssetBundle和Asset)

本节主要叙述下,资源的释放问题。
一、咱们准备了下两个资源,而且要作打包处理。
这里写图片描述web

代码的代码,很简陋,只是为了说明问题。代码以下:svg

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

public class AssetBundleCreator
{
    [MenuItem("AssetBundle/Build")]
    private static void BuildBundle()
    {
        string outDir = "Bundles";
        if (!Directory.Exists(outDir))
        {
            Directory.CreateDirectory(outDir);
        }

        AssetBundleBuild[] buildList = new AssetBundleBuild[1];
        buildList[0].assetBundleName = "bundleDemo";
        string[] bundleAssets = new string[2];
        bundleAssets[0] = @"Assets\Prefabs\Cube.prefab";
        bundleAssets[1] = @"Assets\Prefabs\bg.png";

        buildList[0].assetNames = bundleAssets;
        BuildPipeline.BuildAssetBundles(outDir, buildList, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeB`````````````
ildTarget);
    }
}

打包的结果:
这里写图片描述函数

二、测试过程
2.1 测试界面以下:
这里写图片描述测试

2.2 执行函数LoadBundleui

private void LoadBundle(GameObject go)
    {
        StartCoroutine(LoadAssetBundle());
    }
 private IEnumerator LoadAssetBundle()
    {
        string assetBundlePath = Application.dataPath + @"\..\Bundles\bundleDemo";
        WWW www = new WWW(assetBundlePath);

        while (!www.isDone)
        {
            yield return null;
        }

        m_bundle = www.assetBundle;
        Debug.LogError("LoadAssetBundle over!");
    }

此时内存里面只有一个镜像文件,咱们能够经过profile观测到:
这里写图片描述spa

2.3 执行一次UnloadBundleFalse,观察这个镜像文件是否被卸载掉了。3d

private void UnloadBundleFalse(GameObject go)
    {
        m_bundle.Unload(false);
        Debug.LogError("UnloadBundleFalse over!");
    }

此时AssetBundle镜像不存在了。
这里写图片描述code

2.4 执行一次LoadBundle和LoadAsset,观察内存变换。
从新运行游戏,执行一次LoadBundle,上面已经叙述。而后执行一次LoadAsset。xml

private void LoadAsset(GameObject go)
    {
        m_textureAsset = (Texture)m_bundle.LoadAsset("bg", typeof(Texture));
        m_texture.mainTexture = m_textureAsset;
        Debug.LogError("LoadAsset over!");
    }

此时,咱们load一张图片赋值给了UITexture组件。观察Profile的内存状态:
这里写图片描述
再看镜像文件也在:
这里写图片描述blog

2.5 执行一次LoadBundle、LoadAsset和UnloadAsset,观察镜像文件是否在Asset是否在?

private void UnloadAsset(GameObject go)
    {
        if (m_textureAsset != null)
        {
            Resources.UnloadAsset(m_textureAsset);
        }
        Debug.LogError("UnloadAsset over!");
    }

镜像文件在:
这里写图片描述
Asset不在了:
这里写图片描述

2.6 执行一次LoadBundle、LoadAsset和UnloadBundleTrue

private void UnloadBundleTrue(GameObject go)
    {
        m_bundle.Unload(true);
        Debug.LogError("UnloadBundleTrue over!");
    }

镜像文件不在了:
这里写图片描述
Asset也不在了:
这里写图片描述

2.7 删除物体(绑定这个脚本的物体),而后执行一次 Resources.UnloadUnusedAssets();
测试代码:

private void DestroyComponent(GameObject go)
    {
        StartCoroutine(DestroyComp());
    }

    private IEnumerator DestroyComp()
    {
        Destroy(m_destroyComp.gameObject);
        yield return null;
        Resources.UnloadUnusedAssets();
    }

镜像文件在:
这里写图片描述
Asset不在:
这里写图片描述

叙述完毕。

总结:
一、镜像文件必须用Unload(true),才能卸载掉。
二、Asset的卸载有两种方法,一种是指定类型资源强制卸载,函数为:
Resources.UnloadAsset(m_textureAsset); //这里的指定类型的资源不能是GameObject、Component,指定是Material、Texture、Mesh、AudioClip资源。
第二种卸载方式:Resources.UnloadUnusedAssets(); 这个要求必须是Asset在毫无其余引用的状况下,才能被卸载。所谓的毫无其余引用,好比你的texture被一个UI元素使用,或者被一个脚本的变量使用,没有赋值为null,这些都算做是有引用,那么即便你使用这个函数,也不能卸载Asset资源。另外补充说明一点就是:
Resources.UnloadUnusedAssets();和Resources.UnloadAsset(m_textureAsset);
前者效率很低,由于是遍历场景中的全部无引用的资源而后卸载;后者是指定卸载某一个资源,因此效率高。前者在场景切换的时候会被Unity自动调用一次,后者不会。
三、关于镜像文件和Asset以及GameObject的关系,我想画一个图来解释:
这里写图片描述

over!关于资源管理的代码,还没有完成,待叙。
最后给出,项目的完整代码:https://pan.baidu.com/s/1rvgPoTgMPNkpMOjrqSnP6g