本节主要叙述下,资源的释放问题。
1、我们准备了下两个资源,并且要做打包处理。
代码的代码,很简陋,只是为了说明问题。代码如下:
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、测试过程
2.1 测试界面如下:
2.2 执行函数LoadBundle
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观测到:
2.3 执行一次UnloadBundleFalse,观察这个镜像文件是否被卸载掉了。
private void UnloadBundleFalse(GameObject go){m_bundle.Unload(false);Debug.LogError("UnloadBundleFalse over!");}
此时AssetBundle镜像不存在了。
2.4 执行一次LoadBundle和LoadAsset,观察内存变换。
重新运行游戏,执行一次LoadBundle,上面已经叙述。然后执行一次LoadAsset。
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的内存状态:
再看镜像文件也在:
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不在:
叙述完毕。
总结:
1、镜像文件(bundle)用Unload(true),Unload(false)都可卸载掉。
2、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自动调用一次,后者不会。
3、关于镜像文件和Asset以及GameObject的关系,我想画一个图来解释:
over!关于资源管理的代码,尚未完成,待叙。
最后给出,项目的完整代码:https://pan.baidu.com/s/1rvgPoTgMPNkpMOjrqSnP6g