通過AssetBundle加載遊戲資源,分爲兩步:
- 加載AssetBundle對象。
- 通過AssetBundle對象加載需要的資源。
本地沒有AssetBundle,需要先從網絡下載AssetBundle:
1.Unity5.2之前推薦使用 WWW.LoadFromCacheOrDownload(),慢慢被淘汰掉了。(異步加載,每次打包都需要更新資源版本,下載後緩存的資源也不好管理)
- Unity會先判斷本地有無"url"的文件,如果沒有,就會根據URL去下載相應的文件。然後在本地存儲一下文件,並記錄相應的版本號。
- Unity會先判斷本地有"url"的文件,本地的版本號<API傳入的版本號,此時Unity也會去下載最新的文件,然後覆蓋本地的此文件,然後記錄下最新的版本號。
- Unity會先判斷本地有"url"的文件,本地的版本號>=API傳入的版本號,此時Unity會從本地直接取,並且加載相應的文件返回。
-
Caching.ClearCache() 刪除本地緩存。
2.WWW下載保存AssetBundle到本地
/// <summary>
///從服務器下載到本地
/// </summary>
/// <param name="AssetsHost">服務器路徑</param>
/// <param name="AssetName">請求資源名稱</param>
/// <param name="saveLocalPath">保存到本地路徑,一般存在Application.persistentDataPath</param>
/// <returns></returns>
IEnumerator DownLoadAssetsWithDependencies2Local(string AssetsHost, string AssetName, string saveLocalPath)
{
WWW tempWwwAsset = new WWW(AssetsHost + "/" + AssetName);
//獲取加載進度
yield return tempWwwAsset;
//直接讀取AssetBundle
AssetBundle temp = tempWwwAsset.assetBundle;
//保存到本地
Stream tempStream = null;
FileInfo fileInfo = new FileInfo(saveLocalPath + "/" + AssetName);
if (fileInfo.Exists)
{
fileInfo.Delete();
}
//如果此文件不存在則創建
tempStream = fileInfo.Create();
//寫入
tempStream.Write(tempWwwAsset.bytes, 0, tempWwwAsset.bytes.Length);
tempStream.Flush();
//關閉流
tempStream.Close();
//銷燬流
tempStream.Dispose();
Debug.Log(name + "成功保存到本地~");
}
3.UnityWebRequest下載AssetBundle到本地(據說用www下載在IOS平臺會出現卡死,用這不會)
IEnumerator Download(Action callback = null)
{
string tempSrcUrl = string.Empty;//傳入資源網址
string saveLocalPath = string.Empty;//保存到本地的路勁
UnityWebRequest tempWebRequest = UnityWebRequest.Get(tempSrcUrl);
//設置超時,若m_webRequest.SendWebRequest()連接超時會返回,且isNetworkError爲true
tempWebRequest.timeout = 30;
yield return tempWebRequest.SendWebRequest();
if(tempWebRequest.isNetworkError) {
Debug.Log("Download Error:" + tempWebRequest.error);
} else {
//直接讀取AssetBundle
AssetBundle tempAssetBundle = (tempWebRequest.downloadHandler as
DownloadHandlerAssetBundle).assetBundle;
//保存到本地
string tempAssetBundleName = (tempWebRequest.downloadHandler as
DownloadHandlerAssetBundle).assetBundle.name;
byte[] bytes = tempWebRequest.downloadHandler.data;
Stream tempStream = null;
FileInfo fileInfo = new FileInfo(saveLocalPath + "/" + tempAssetBundleName);
if (fileInfo.Exists)
{
fileInfo.Delete();
}
//如果此文件不存在則創建
tempStream = fileInfo.Create();
//寫入
tempStream.Write(bytes, 0, bytes.Length);
tempStream.Flush();
//關閉流
tempStream.Close();
//銷燬流
tempStream.Dispose();
Debug.Log(name + "成功保存到本地~");
tempWebRequest.Dispose();
tempWebRequest = null;
}
if(callback != null) {
callback();
}
}
AssetBundle加載:
AssetBundle.LoadFromFile() - 同步加載
AssetBundle tempLogo = AssetBundle.LoadFromFile(AssetBundlesOutputPath + "/logo.unity3d");
AssetBundle.LoadFromFileAsync() - 異步加載
IEnumerator LoadAsyncCoroutine(string path, Action<AssetBundle> callback) {
AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path);
yield return abcr;
callback(abcr.assetBundle);
}
WWW - 異步加載
IEnumerator LoadFromWWWCoroutine(string path, Action<AssetBundle> callback)
{
WWW www = new WWW(path);
yield return www;
callback(www.assetBundle);
www.Dispose();
www = null;
}
LoadFromMemoryAsync - 異步加載
IEnumerator LoadAB(string _filePath)
{
byte[] tempByteAry = File.ReadAllBytes(_filePath);
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(tempByteAry);
yield return request;
AssetBundle ab = request.assetBundle;
}
WWW.LoadFromCacheOrDownload - 異步加載
IEnumerator LoadCacheOrDownloadFromFile(string path)
{
while (Caching.ready == false)
yield return null;
WWW www = WWW.LoadFromCacheOrDownload(path, 1);
yield return www;
if( !string.IsNullOrEmpty(www.error) )
{
Debug.Log(www.error);
yield break;
}
AssetBundle ab = www.assetBundle;
}
AssetBundle加載後,從已加載的AssetBundle中加載資源:
AssetBundle tempAssetBundle = 通過上邊代碼獲取的AssetBundle;
string[] tempAssetNames = tempAssetBundle.GetAllAssetNames();//此AssetBundle中包含的所有資源名稱
tempAssetBundle.LoadAsset("");//通過資源名稱從AssetBundle加載指定的資源
tempAssetBundle.LoadAllAssets();//加載當前資源包中所有的資源
tempAssetBundle.LoadAssetAsync("");//從資源包中異步加載資源
加載AssetBundle時候,此AssetBundle依賴其他AssetBundle,需要先加載其他AssetBundle。
[MenuItem("AssetsBundle/Load")]
static void LoadAssetbundle()
{
LoadAssetBundleManifest();
LoadBundle();
}
//本地AssetBundle存儲路勁 自己存哪讀哪
private static string m_rootFilePath = Application.dataPath + "/StreamingAssets/";
private static AssetBundleManifest manifest = null;
// 加載Manifest
private static void LoadAssetBundleManifest()
{
var bundle = AssetBundle.LoadFromFile(System.IO.Path.Combine(m_rootFilePath,"StreamingAssets"));
manifest = bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
// 壓縮包釋放掉
bundle.Unload(false);
bundle = null;
}
//加載AssetBundle前,先加載AssetBundle依賴的AssetBundle
private static void LoadBundle()
{
string bundleName = "logo";
// GetAllDependencies會返回直接和間接關聯的AssetBundle 當前AssetBundle所依賴的所有AssetBundle
// 加載依賴包沒有順序要求,
string[] dependence = manifest.GetAllDependencies(bundleName);
for (int i = 0; i < dependence.Length; ++i )
{
//這地方同步加載,異步也可以(AssetBundle.LoadFromFileAsync)
AssetBundle.LoadFromFile(System.IO.Path.Combine(m_rootFilePath, dependence[i]));
}
//加載完所有依賴的AssetBundle,加載本身
var bundle = AssetBundle.LoadFromFile(System.IO.Path.Combine(m_rootFilePath, bundleName));
//這裏不需要手動LoadAsset 依賴的AssetBundle中資源
//LoadAsset(logo) 資源的時候自動加載與它關聯的Asset
GameObject tempGameObject = bundle.LoadAsset<GameObject>("logo");
GameObject tempGameObject1 = Instantiate(tempGameObject) as GameObject;
}
//這裏不需要手動LoadAsset 依賴的AssetBundle中資源
//LoadAsset(logo) 資源的時候自動加載與它關聯的Asset
AssetBundle中可以實例化的類型:
Texture | 設置read/write enabled後可以 |
AudioClip | 不可以 |
Scene | 可以 |
TextAsset | 可以,但一般沒有必要 |
Material | 可以 |
Shader | 可以 |
Mesh | 可以 |
Animator | 可以 |
Animation | 可以 |
TerrainData | 可以 |
GameObject | 可以,Prefab就是GameObject,一般都是實例化prefab,實例化其他的沒有必要。 |