Unity 资源管理与AssetBundle详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 资源管理与AssetBundle详解相关的知识,希望对你有一定的参考价值。

参考技术A

http://blog.csdn.net/u014230923/article/details/51433455
Unity常用的资源大概有3类:

还有一些平时不太关注的:脚本对象,文本文件,unity自己内置的资源(像新建粒子时的默认材质之类的),这些也是资源。

http://blog.csdn.net/qq_18995513/article/details/51955609
Unity的资源管理模式,包括在编辑器管理(使用AssetDatabase)和在运行时管理(使用Resources和AssetBundle)。

在编辑器内加载卸载资源,并不能在游戏发布时使用,它只能在编辑器内使用。但是,它加载速度快,效率高, 适合在测试时使用

因为只能在编辑器使用,要加个宏防止报错:

https://docs.unity3d.com/ScriptReference/Resources.UnloadAsset.html

Unloads assetToUnload from memory.

This function can only be called on Assets that are stored on disk.

If there are any references from game objects in the scene to the asset and it is being used then Unity will reload the asset from disk as soon as it is accessed.

需要注意的是,调用Resources.UnloadAsset()来清理资源时,只是标记该资源需要被GC回收,但不是立刻就被回收的。需要调用

运行脚本后,会发现在编辑器里就会出现:Project视窗中多了一个刚创建的1.mat资源。

具体见上面链接

Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时 动态加载,可以指定路径和来源的。

注意下图有一些错误需要更新:

unity创建和加载AssetBundle

先说一下为什么要使用AssetBundle吧,以前做东西一直忽略这个问题,现在认为这个步骤很重要,代码是次要的,决策和为什么这样搞才是关键。

一句话概括吧,AssetBundle实现了资源与服务分离,方便做热更新。

一、创建AssetBundle

两步:1.设置AssetBundleName;2.调用BuildPipeline.BuildAssetBundles。详细过程如下:

设置AssetBundleName有两种方式,分为手动和代码

先讲手动,找到你需要被打包的文件,然后如下图

方式2,代码设置这个AssetBundleName,代码如下,创建bundle的代码也一起贴上了:

using UnityEngine;
using System.IO;  
#if UNITY_EDITOR
using UnityEditor;
#endif

public class BuildBundleMenu : MonoBehaviour {
	
	public static string sourcePathPrefab = Application.dataPath + "/_Creepy_Cat/Realistic_Weather_Effects/_Prefabs/";
	public static string sourcePathMater = Application.dataPath + "/_Creepy_Cat/Realistic_Weather_Effects/_Materials/";
	
	#if UNITY_EDITOR
	[MenuItem( "Example/Build Asset Bundles" )]
	static void BuildABs( )
	{
		
		ClearAssetBundlesName ();  
   		
		FindAllFile (sourcePathPrefab); 
		FindAllFile (sourcePathMater); 
		
		// Put the bundles in a folder called "ABs" within the Assets folder.
		BuildPipeline.BuildAssetBundles( "Assets/ABs", BuildAssetBundleOptions.UncompressedAssetBundle, BuildTarget.StandaloneOSXIntel64);
	}
	
	
	/// <summary>  
	/// 清除之前设置过的AssetBundleName,避免产生不必要的资源也打包  
	/// 之前说过,只要设置了AssetBundleName的,都会进行打包,不论在什么目录下  
	/// </summary>  
	static void ClearAssetBundlesName()  
	{  
		int length = AssetDatabase.GetAllAssetBundleNames ().Length;  
		Debug.Log (length);  
		string[] oldAssetBundleNames = new string[length];  
		for (int i = 0; i < length; i++)   
		{  
			oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];  
		}  
   
		for (int j = 0; j < oldAssetBundleNames.Length; j++)   
		{  
			AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j],true);  
		}  
		length = AssetDatabase.GetAllAssetBundleNames ().Length;  
		Debug.Log (length);  
	}  
	
   	/// <summary>
   	/// 遍历文件夹里面的所有文件夹和文件
   	/// </summary>
   	/// <param name="source"></param>
	static void FindAllFile(string source)  
	{  
		DirectoryInfo folder = new DirectoryInfo (source);  
		FileSystemInfo[] files = folder.GetFileSystemInfos ();  
		int length = files.Length;  
		for (int i = 0; i < length; i++) {  
			if(files[i] is DirectoryInfo)  
			{  
				FindAllFile(files[i].FullName);  
			}  
			else  
			{  
				if(!files[i].Name.EndsWith(".meta"))  
				{  
					SetAssetName (files[i].FullName);  
				}  
			}  
		}  
	}  
   
	/// <summary>
	/// 为需要打包的文件设置assetName.
	/// </summary>
	/// <param name="source"></param>
	static void SetAssetName(string source)  
	{    
		string _assetPath = "Assets" + source.Substring (Application.dataPath.Length);  
		//string _assetPath2 = source.Substring (Application.dataPath.Length + 1);   
		//在代码中给资源设置AssetBundleName  
		AssetImporter assetImporter = AssetImporter.GetAtPath (_assetPath);  
		//string assetName = _assetPath2.Substring (_assetPath2.IndexOf("/") + 1);  
		//assetName = assetName.Replace(Path.GetExtension(assetName),".unity3d");  
		//assetImporter.assetBundleName = assetName;
		assetImporter.assetBundleName = "Weather.unity3d";
	}  
	#endif
}

  菜单栏会出现这个,点一下就可以了,bundle创建完成。注意打bundle前要现在Assets目录下新建一个ABs文件夹,打的bundle都在这个文件夹里面。

 

注:只要设置了AssetBundleName的,都会进行打包,不论在什么目录下。

二、bundle的加载

直接贴代码吧

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

public class LoadAssetbundle : MonoBehaviour {

	private string pathurl = "";
	// Use this for initialization
	void Start () {
		string pathPrefab = "file://" + Application.dataPath + "/ABs/weather.unity3d";
		
		StartCoroutine (LoadALLGameObject(pathPrefab));
	}

	//读取全部资源  
	private IEnumerator LoadALLGameObject(string path)  
	{  
		
		WWW bundle = new WWW(path);  

		yield return bundle;  

		//通过Prefab的名称把他们都读取出来  
		Object  obj0 =  bundle.assetBundle.LoadAsset("CloudStorm_02_8x8-64.prefab");   
		
		//加载到游戏中     
		yield return Instantiate(obj0);  
		bundle.assetBundle.Unload(false);  
	} 
}

  

 

以上是关于Unity 资源管理与AssetBundle详解的主要内容,如果未能解决你的问题,请参考以下文章

[Unity]浅谈AssetBundle的依赖关系打包与加载

AssetBundle理论篇

Unity5 怎样做资源管理和增量更新

Unity中的AssetBundle

unity创建和加载AssetBundle

unity3d开发2d游戏中Assetbundle有啥作用