AssetBundle加载与卸载

1.生成Asset Bundle

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

public class BuildAssetBundle :  Editor{

	[MenuItem("Tools/BuildAssetBundle")]
	public static void BuildBundle()
	{
		string abPath = Path.Combine(Application.streamingAssetsPath,"AssetBundle");
		if (!Directory.Exists(abPath))
		{
			Directory.CreateDirectory(abPath);
		}
		BuildPipeline.BuildAssetBundles(abPath, BuildAssetBundleOptions.ChunkBasedCompression,EditorUserBuildSettings.activeBuildTarget);
		AssetDatabase.Refresh();
	}

	[MenuItem("Tools/CreatScriptTableAsset")]
	public static void CreatScriptTableAsset()
	{
		ScriptTableTest test = ScriptableObject.CreateInstance<ScriptTableTest>();
		AssetDatabase.CreateAsset(test, "Assets/Resources/ScriptTableTest.asset");
		AssetDatabase.SaveAssets();
		AssetDatabase.Refresh();
	}
}

 

2.AssetBundleManager 管理(资源加载和卸载)

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

public enum ABLoadStateEnum
{
	None,
	Loading,
	Loaded,
	Release
}

public enum AssetLoadStateEnum
{
	LoadFail,
	Loading,
	Loaded
}

public class AssetBundleManager : MonoBehaviour {

	private static AssetBundleManager instance;
	public static AssetBundleManager Instance
	{
		get
		{
			return instance;
		}
	}
	private Coroutine mRequestABCor;
	private string mAssetBundlePath;
	private Dictionary<string, AssetBundleBaseInfo> mABBaseInfoDic = new Dictionary<string, AssetBundleBaseInfo>();
	public delegate void AssetReqCallBack(UnityEngine.Object obj, string assetName, string assetBundelName);
	private Queue<AssetReq> mAssetReqQueue = new Queue<AssetReq>();
	private List<AssetReq> mAssetReqs = new List<AssetReq>();
	private List<AssetReq> mLoadingAssetReqs = new List<AssetReq>();
	private Dictionary<string, AssetInfo> mLoadedAssetInfoDic = new Dictionary<string, AssetInfo>();
	private Dictionary<string, string> mAssetNameToABNameDic = new Dictionary<string, string>();
	private Dictionary<string, AssetBundleCreateRequest> mAbNameToCreateQequestDic = new Dictionary<string, AssetBundleCreateRequest>();
	private int mMaxLoadAssetReqCount = 5;
	private List<string> mDelayReleaseABNames = new List<string>();
	private List<bool> mLoadingAssetFlags = new List<bool>();
	private int mMaxReleaseAssetCount = 20;
	private float mTimeInterval = 50;
	private float mTimer;


	private void Awake()
	{
		instance = this;
		for (int i = 0; i < mMaxLoadAssetReqCount; i++)
		{
			mLoadingAssetFlags.Add(false);
		}
	}

	#region 获取所有资源依赖

	private void Start()
	{
		mAssetBundlePath = Path.Combine(Application.streamingAssetsPath, "AssetBundle/AssetBundle");
		if (mRequestABCor != null)
		{
			StopCoroutine(mRequestABCor);
			mRequestABCor = null;
		}
		mRequestABCor = StartCoroutine(RequestAssetBundle(0));
	}

	public IEnumerator RequestAssetBundle(int version)
	{
		AssetBundleCreateRequest abCreateRequest = AssetBundle.LoadFromFileAsync(mAssetBundlePath);
		yield return abCreateRequest;
		if (abCreateRequest.isDone)
		{
			if (abCreateRequest.assetBundle != null)
			{
				AssetBundleRequest abRequest = abCreateRequest.assetBundle.LoadAllAssetsAsync();
				yield return abRequest;
				if (abRequest.isDone)
				{
					AssetBundleManifest abMainfest = abRequest.asset as AssetBundleManifest;
					if (abMainfest != null)
					{
						string[] allABNames = abMainfest.GetAllAssetBundles();
						for (int i = 0; i < allABNames.Length; i++)
						{
							string abName = allABNames[i];
							string[] allDependence = abMainfest.GetAllDependencies(abName);
							AssetBundleBaseInfo abBaseInfo = new AssetBundleBaseInfo(abName, allDependence, version);
							mABBaseInfoDic.Add(abName, abBaseInfo);
						}
					}
				}
			}
		}
	}

	#endregion

	#region 加载资源
	public void LoadAsset<T>(string assetName, string assetBundleName, AssetReqCallBack callBack) where T:UnityEngine.Object
	{
		if (mLoadedAssetInfoDic.ContainsKey(assetName))
		{
			callBack(mLoadedAssetInfoDic[assetName].assetObj, assetName, assetBundleName);
		}
		else
		{
			AssetReq assetReq = new AssetReq(assetName, assetBundleName, callBack, false);
			mAssetReqQueue.Enqueue(assetReq);
			AddAssetReqToList();
			StartLoadAsset<T>();
		}
	}

	private void AddAssetReqToList()
	{
		mLoadingAssetReqs.Clear();
		for (int i = 0; i < mMaxLoadAssetReqCount; i++)
		{
			if (mAssetReqQueue.Count <= 0)
			{
				break;
			}
			else
			{
				AssetReq assetReq = mAssetReqQueue.Dequeue();
				if (assetReq != null)
				{
					mLoadingAssetReqs.Add(assetReq);
				}
			}
		}
	}

	private void StartLoadAsset<T>() where T:UnityEngine.Object
	{
		for (int i = 0; i < mLoadingAssetReqs.Count; i++)
		{
			AssetReq assetReq = mLoadingAssetReqs[i];
			if (assetReq != null)
			{
				StartCoroutine(LoadAssetCor<T>(assetReq, assetReq.assetBundleName, i));
			}
		}
	}

	private IEnumerator LoadAssetCor<T>(AssetReq assetReq, string abName, int curIndex) where T:UnityEngine.Object
	{
		if (assetReq == null)
		{
			if (!CheckIsHaveAssetBundle(abName))
			{
				yield break;
			}
			AssetBundleBaseInfo abBaseInfo = mABBaseInfoDic[abName];
			if (abBaseInfo.abLoadState == ABLoadStateEnum.Loaded)
			{
				yield break;
			}
			while (abBaseInfo.abLoadState == ABLoadStateEnum.Loading)
			{
				yield return null;
			}
			abBaseInfo.abLoadState = ABLoadStateEnum.Loading;
			string abPath = Application.streamingAssetsPath + "/AssetBundle/" + abBaseInfo.assetBundleName;
			AssetBundleCreateRequest abCreateRequest = AssetBundle.LoadFromFileAsync(abPath);
			yield return abCreateRequest;
			if (abCreateRequest.isDone)
			{
				abBaseInfo.abLoadState = ABLoadStateEnum.Loaded;
				abBaseInfo.refCount++;
			}
		}
		else
		{
			if (!CheckIsHaveAssetBundle(abName))
			{
				yield break;
			}
			AssetBundleBaseInfo abBaseInfo = mABBaseInfoDic[abName];
			while (abBaseInfo.abLoadState == ABLoadStateEnum.Loading)
			{
				yield return null;
			}
			if (abBaseInfo.abLoadState == ABLoadStateEnum.None)
			{
				abBaseInfo.abLoadState = ABLoadStateEnum.Loading;
			}
			if (mDelayReleaseABNames.Contains(assetReq.assetBundleName))
			{
				mDelayReleaseABNames.Remove(assetReq.assetBundleName);
			}
			for (int i = 0; i < abBaseInfo.dependceArr.Length; i++)
			{
				string assetBundlename = abBaseInfo.dependceArr[i];
				StartCoroutine(LoadAssetCor<T>(null, assetBundlename,-1));
			}
			AssetBundleCreateRequest abCreateRequest = null;
			string abPath = Application.streamingAssetsPath + "/AssetBundle/" + abBaseInfo.assetBundleName;
			if (mAbNameToCreateQequestDic.ContainsKey(abName))
			{
				abCreateRequest = mAbNameToCreateQequestDic[abName];
			}
			else
			{
				abCreateRequest = AssetBundle.LoadFromFileAsync(abPath);
				yield return abCreateRequest;
			}
			if (abCreateRequest.isDone)
			{
				abBaseInfo.abLoadState = ABLoadStateEnum.Loaded;
				abBaseInfo.assetBundle = abCreateRequest.assetBundle;
				if (!mAbNameToCreateQequestDic.ContainsKey(abName))
				{
					mAbNameToCreateQequestDic.Add(abName, abCreateRequest);
				}
			}
			if (abBaseInfo.abLoadState == ABLoadStateEnum.Loaded)
			{
				if (!abBaseInfo.assetInfoDic.ContainsKey(assetReq.assetBundleName))
				{
					AssetInfo assetInfo = new AssetInfo(assetReq.assetName,null, AssetLoadStateEnum.Loading);
					Dictionary<string, AssetInfo> dic = new Dictionary<string, AssetInfo>();
					dic.Add(assetReq.assetName, assetInfo);
					abBaseInfo.assetInfoDic.Add(assetReq.assetBundleName, dic);
					AssetBundleRequest abRequest = abBaseInfo.assetBundle.LoadAssetAsync<T>(assetReq.assetName);
					yield return abRequest;
					if (abRequest.isDone)
					{
						assetInfo.assetObj = abRequest.asset;
						string assetName = abRequest.asset.name;
						if (!mLoadedAssetInfoDic.ContainsKey(assetName))
						{
							mLoadedAssetInfoDic.Add(assetName, assetInfo);
						}
						if (!mAssetNameToABNameDic.ContainsKey(assetName))
						{
							mAssetNameToABNameDic.Add(assetName,abName);
						}
					}
				}
				else
				{
					AssetInfo assetInfo = new AssetInfo(assetReq.assetName, null, AssetLoadStateEnum.Loading);
					if (!abBaseInfo.assetInfoDic.ContainsKey(assetReq.assetBundleName))
					{
						Dictionary<string, AssetInfo> dic = new Dictionary<string, AssetInfo>();
						dic.Add(assetReq.assetName, assetInfo);
						abBaseInfo.assetInfoDic.Add(assetReq.assetBundleName, dic);
					}
					else
					{
						if (!abBaseInfo.assetInfoDic[assetReq.assetBundleName].ContainsKey(assetReq.assetName))
						{
							abBaseInfo.assetInfoDic[assetReq.assetBundleName].Add(assetReq.assetName, assetInfo);
						}
					}
					AssetBundleRequest abRequest = abBaseInfo.assetBundle.LoadAssetAsync<T>(assetReq.assetName);
					yield return abRequest;
					if (abRequest.isDone)
					{
						assetInfo.assetObj = abRequest.asset;
						string assetName = abRequest.asset.name;
						if (!mLoadedAssetInfoDic.ContainsKey(assetName))
						{
							mLoadedAssetInfoDic.Add(assetName, assetInfo);
						}
						if (!mAssetNameToABNameDic.ContainsKey(assetName))
						{
							mAssetNameToABNameDic.Add(assetName, abName);
						}
					}
				}
				UnityEngine.Object assetObj = abBaseInfo.assetInfoDic[assetReq.assetBundleName][assetReq.assetName].assetObj;
				assetReq.assetReqCallBack(assetObj, assetReq.assetName, abBaseInfo.assetBundleName);
			}
			abBaseInfo.refCount++;
			mLoadingAssetFlags[curIndex] = false;
			yield return new WaitForEndOfFrame();
			if (!mLoadingAssetFlags.Contains(true))
			{
				if (mAssetReqQueue.Count > 0)
				{
					AddAssetReqToList();
					StartLoadAsset<T>();
				}
			}
		}
	}

	private bool CheckIsHaveAssetBundle(string abName)
	{
		return mABBaseInfoDic.ContainsKey(abName);
	}

	#endregion

	#region 释放资源

	public void ReleaseAsset(string abName,bool isDelayRelease, AssetReqCallBack callBack)
	{
		if (mABBaseInfoDic.ContainsKey(abName))
		{
			AssetBundleBaseInfo abBaseInfo = mABBaseInfoDic[abName];
			abBaseInfo.refCount--;
			if (abBaseInfo.refCount < 0)
			{
				abBaseInfo.refCount = 0;
			}
			if (isDelayRelease)
			{
				mDelayReleaseABNames.Add(abName);
			}
			else
			{
				if (abBaseInfo.abLoadState == ABLoadStateEnum.Loaded && abBaseInfo.assetBundle != null && abBaseInfo.refCount == 0)
				{
					UnLoadAssetBundle(abName);
				}
			}
			if (callBack != null)
			{
				callBack(null,null,abName);
			}
		}
	}

	private void UnLoadAssetBundle(string abName)
	{
		AssetBundleBaseInfo abBaseInfo = mABBaseInfoDic[abName];
		if (abBaseInfo != null)
		{
			abBaseInfo.assetInfoDic.Clear();
			abBaseInfo.assetBundle.Unload(true);
			abBaseInfo.abLoadState = ABLoadStateEnum.None;
			abBaseInfo.assetBundle = null;
			if (mAbNameToCreateQequestDic.ContainsKey(abName))
			{
				mAbNameToCreateQequestDic.Remove(abName);
			}
			foreach (var item in mAssetNameToABNameDic.Keys)
			{
				if (mAssetNameToABNameDic[item].Equals(abName))
				{
					Debug.Log("UnLoadAssetBundle.assetName " + item + " abName " + abName);
					mLoadedAssetInfoDic.Remove(item);
				}
			}
			Debug.Log("UnLoadAssetBundle.abName " + abName);
		}
	}

	private void DelayReleaseAsset()
	{
		if (mDelayReleaseABNames.Count > mMaxReleaseAssetCount)
		{
			int removeIndex = 0;
			for (int i = 0; i < mDelayReleaseABNames.Count; i++)
			{
				string abName = mDelayReleaseABNames[i];
				UnLoadAssetBundle(abName);
				removeIndex++;
			}
			mDelayReleaseABNames.RemoveRange(0, removeIndex);
		}
	}

	private void Update()
	{
		if (mTimer >= mTimeInterval)
		{
			DelayReleaseAsset();
		}
		else
		{
			mTimer += Time.deltaTime;
		}
	}

	#endregion

	public class AssetBundleBaseInfo
	{
		public string assetBundleName;
		public string[] dependceArr;
		public int refCount;
		public int version;
		public AssetBundle assetBundle;
		public ABLoadStateEnum abLoadState;
		public Dictionary<string, Dictionary<string, AssetInfo>> assetInfoDic = new Dictionary<string, Dictionary<string, AssetInfo>>();

		public AssetBundleBaseInfo(string abName, string[] dependences, int version)
		{
			assetBundleName = abName;
			dependceArr = dependences;
			this.version = version;
		}
	}

	public class AssetInfo
	{
		public UnityEngine.Object assetObj;
		public string assetName;
		public AssetLoadStateEnum assetLoadStateEnum;

		public AssetInfo(string assetName, UnityEngine.Object asset, AssetLoadStateEnum state)
		{
			assetObj = asset;
			assetLoadStateEnum = state;
		}
	}

	public class AssetReq
	{
		public string assetName;
		public string assetBundleName;
		public AssetReqCallBack assetReqCallBack;
		public bool isDelay;

		public AssetReq(string assetName, string abName, AssetReqCallBack callBack, bool isDelay)
		{
			this.assetName = assetName;
			assetBundleName = abName;
			assetReqCallBack = callBack;
			this.isDelay = isDelay;
		}
	}
}

 

3.加载资源

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Main : MonoBehaviour {

	public Button loadAssetBtn;
	public Button releaseAssetBtn;
	public Button loadBgBtn;
	public Button releaseBgBtn;
	public Button loadScriptTabelBtn;
	public Button releasecriptTabelBtn;
	public Image nameImg;
	public Image bgImg;
	public Text scriptTabel_text;

	private void Start()
	{
		loadAssetBtn.onClick.AddListener(LoadImg);
		releaseAssetBtn.onClick.AddListener(ReleaseImg);
		loadBgBtn.onClick.AddListener(LoadBg);
		releaseBgBtn.onClick.AddListener(ReleaseBg);
		loadScriptTabelBtn.onClick.AddListener(LoadScriptTable);
		releasecriptTabelBtn.onClick.AddListener(ReleaseScriptTable);
	}

	private void LoadCube()
	{
		AssetBundleManager.Instance.LoadAsset<GameObject>("Cube","prefab/cube",(obj,assetName,assetBundleName)=> 
		{
			GameObject go = Instantiate(obj) as GameObject;
		});
	}

	private void ReleaseCube()
	{
		AssetBundleManager.Instance.ReleaseAsset("prefab/cube",false,null);
	}

	private void LoadImg()
	{
		AssetBundleManager.Instance.LoadAsset<Sprite>("wy_bg_19", "ui/common",(obj, assetName, assetBundleName) =>
		{
			Sprite sprite = (Sprite)obj;
			nameImg.sprite = sprite;
		});
	}

	private void ReleaseImg()
	{
		AssetBundleManager.Instance.ReleaseAsset("ui/common", false, null);
	}

	private void LoadBg()
	{
		AssetBundleManager.Instance.LoadAsset<Sprite>("drawCardBg1", "ui/common", (obj, assetName, assetBundleName) =>
		{
			Sprite sprite = (Sprite)obj;
			bgImg.sprite = sprite;
		});
	}

	private void ReleaseBg()
	{
		AssetBundleManager.Instance.ReleaseAsset("ui/common", false, null);
	}

	private void LoadScriptTable()
	{
		AssetBundleManager.Instance.LoadAsset<ScriptableObject>("ScriptTableTest", "scripttable/scripttabletest", (obj, assetName, assetBundleName) =>
		{
			ScriptTableTest scriptTabel = (ScriptTableTest)obj;
			Debug.Log("LoadScriptTable.scriptTabel " + scriptTabel);
			scriptTabel_text.text = scriptTabel.ID + "---" + scriptTabel.name;
		});
	}

	private void ReleaseScriptTable()
	{
		AssetBundleManager.Instance.ReleaseAsset("scripttable/scrpttabletest", false, null);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值