本节主要叙述下,资源的释放问题。
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 执行函数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!");
}
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!");
}
2.6 执行一次LoadBundle、LoadAsset和UnloadBundleTrue
private void UnloadBundleTrue(GameObject go)
{
m_bundle.Unload(true);
Debug.LogError("UnloadBundleTrue over!");
}
2.7 删除物体(绑定这个脚本的物体),然后执行一次 Resources.UnloadUnusedAssets();
测试代码:
private void DestroyComponent(GameObject go)
{
StartCoroutine(DestroyComp());
}
private IEnumerator DestroyComp()
{
Destroy(m_destroyComp.gameObject);
yield return null;
Resources.UnloadUnusedAssets();
}
叙述完毕。
总结:
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