关闭

【Unity】Unity中资源动态加载的两种方式之AssetsBundle

标签: unityunity资源加载编辑器
21261人阅读 评论(0) 收藏 举报
分类:
首先要说的是,我们的工程中有2个脚本,分别是:
Build(编辑器类脚本,无需挂载到任何物体),但是必须要把Build脚本放到Editor文件夹中
Load脚本,挂载到摄像机上<pre name="code" class="csharp">using UnityEngine;
using System.Collections;
using UnityEditor;

public class Build : MonoBehaviour
{
	// 编辑器类
	[MenuItem("Build/BuildAsset")]
	// 打包单个资源的方法
	static void BuildAsset ()
	{
		// 将物体打包到/AssetsBundles路径下同时命名为Cube1.assetbundle
		string targetPath = Application.dataPath + "/AssetsBundles/Cube1.assetbundle"; 
		// BuildPipeline 打包用 Selection (Selection.activeObject 在编辑器中选中的对象)
		// 第二个参数null,是打包多个资源的时候用的,多个资源就是数组,单个资源的时候这个参数不用写
		// 第三个参数是路径,你想把这个资源放到什么位置就写什么,并且还要命名为.assetbundl格式
		BuildPipeline.BuildAssetBundle (Selection.activeObject, null, targetPath);
		// 刷新资源,直接可以在unity中看到刚才打包的东西
		AssetDatabase.Refresh();
	}

	// --------------------------------------------------------------------------------


	[MenuItem("Build/BuildMultiAsset")]
	// 打包多个资源的时候使用这个方法
	static void BuildMultiAsset()
	{
		// 将物体打包到/AssetsBundles路径下同时命名为Cubes.assetbundle
		string target = Application.dataPath + "/AssetsBundles/Cubes.assetbundle";
		// 因为打包多个游戏对象,所以是一个数组,typr(Object)表示,只要选择的物体是Object类型就可以
		// 并且选择的模式是深度资源搜索(具体学名到底叫啥我也忘了。。。),
		// 意思是只要你选择的object对象下面如果还有关联的东西就都会一起打包(unity导出场景的时候应该可以感受到)
		Object[] cubes = Selection.GetFiltered(typeof(Object),SelectionMode.DeepAssets);
		// 打包开始,因为是一堆资源,所以主资源为null,剩下两个参数意思同上
		BuildPipeline.BuildAssetBundle(null,cubes,target);
		// 刷新资源,直接可以在unity中看到刚才打包的东西
		AssetDatabase.Refresh();
	}

	// --------------------------------------------------------------------------------

	[MenuItem("Build/BuildScene")]
	// 打包场景的方法
	static void BuildScene()
	{
		// 场景名字,为什么是数组呢(因为参数里要求这个参数是数组类型。。。。)
		string [] sceneName =  new string[]{Application.dataPath + "/scene1.unity"};
		// 将物体打包到/AssetsBundles路径下同时命名为Scene1.assetbundle
		string targetPath = Application.dataPath + "/AssetsBundles/Scene1.assetbundle";
		// 注意打包的方法名已经变成流类型了,后面的最后一个参数表示你要在上面平台运行
		// iphone平台就是用BuildTarget.iPhone这个参数
		// 安卓平台就是用BuildTarget.Android这个参数
		// 类似参数可以自己查看。。。
		BuildPipeline.BuildStreamedSceneAssetBundle(sceneName,targetPath,BuildTarget.WebPlayer);
		// 刷新资源,直接可以在unity中看到刚才打包的东西
		AssetDatabase.Refresh();
	}
	// --------------------------------------------------------------------------------
	[MenuItem("Build/BuildDependence")]
	static void BuildDependence()
	{
		// 对一些公共参数的定义 //
		// 定义路径文件夹是Application.dataPath读取后的路径 加上 "/AssetBundles"
		string path = Application.dataPath + "/AssetsBundles";
		// 定义资源包的依赖关系选项
		BuildAssetBundleOptions buildOp = BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets;

		// ---------------------------------------------------------------------

		// Push和Pop是成对出现的,他们的作用是维持一个依赖关系
		// 我们当前的资源包关系是这样的:
		/*
			Tex1.assetbundle资源包(Tex1的包里有以下2个资源包)
				c1.assetbundle资源包(c1和c2是平级关系)
				c2.assetbundle资源包	
		*/
		//依赖资源压栈
		BuildPipeline.PushAssetDependencies();

		// 替代之前的selection的手动选择方式
		Object tex = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Tex1.jpg");

		// 所有后续资源将共享这一资源包中的内容,但是你要保证的是,在使用c1和c2这种内层依赖包时
		// 你已经加载了最外层资源包Tex1
		BuildPipeline.BuildAssetBundle(tex, null,path + "/Tex1.assetbundle", buildOp);

		// 这里使用一对Push和Pop是将我们接下来加载的c1资源包和tex依赖起来
		BuildPipeline.PushAssetDependencies();
		Object c1 = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Cube1.prefab");
		BuildPipeline.BuildAssetBundle(c1, null, path + "/c1.assetbundle", buildOp);
		BuildPipeline.PopAssetDependencies();

		// 同上
		BuildPipeline.PushAssetDependencies();
		Object c2 = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Cube2.prefab");
		BuildPipeline.BuildAssetBundle(c2, null,path + "/c2.assetbundle", buildOp);
		BuildPipeline.PopAssetDependencies();

		// 依赖资源出栈
		BuildPipeline.PopAssetDependencies();
		AssetDatabase.Refresh();
	}


}

using UnityEngine;
using System.Collections;

public class Load : MonoBehaviour {
	// 所有公共的路径名开头都是这个文件夹,所以单列出来,简化后面代码
	public static string loadPath  = "file://" + Application.dataPath +"/AssetsBundles";

	// 画一个按钮
	void OnGUI()
	{
		if(GUILayout.Button("LoadTex"))
		{
			StartCoroutine(LoadTex(loadPath));
		}
		if (GUILayout.Button("LoadCube")) {
			// 因为下面的方法都是协同程序,所以需要手动开启协同程序
			StartCoroutine(LoadCube(loadPath));
		}
		if (GUILayout.Button("LoadVersion")) {
			StartCoroutine(LoadVersion(loadPath));
		}
		if (GUILayout.Button("LoadCubes")) {
			StartCoroutine(LoadCubes(loadPath));
		}
		if (GUILayout.Button("LoadScene")) {
			StartCoroutine(LoadScene(loadPath));
		}
	}

	// 协同方法,加载1个cube的方法
	IEnumerator LoadCube (string path)
	{
		// 下载一个已经打包好的assetbundle(打包需要在Build脚本中实现,在工程里手动打包)
		WWW www = new WWW(path + "/Cube1.assetbundle");
		// 返回下载的assetbundle包
		yield return www;
		// 实例化一个cube,游戏物体使用assetbundle中的主资源(因为是单独打包,所以只有一个主资源),后面是实例化物体的位置和角度信息
		Instantiate(www.assetBundle.mainAsset,new Vector3(Random.Range(0,9),Random.Range(0,9),Random.Range(0,9)),Quaternion.identity);
		// 实例化成功后输出资源名字
		print(www.assetBundle.mainAsset);
		// 卸载刚才已经下载的资源在内存中(就是在内存中删除)
		www.assetBundle.Unload(false);
	}


	// 协同方法,加载多个cube的方法
	IEnumerator LoadCubes(string path)
	{
		// 下载一个已经打包好的包含多个游戏对象的资源包
		WWW www = new WWW(path + "/Cubes.assetbundle");
		yield return www;
		// 下载资源包中的其中一个名字叫Cube1的物体(这个名字一定是在刚才下载的那个包里有的)
		Instantiate(www.assetBundle.Load("Cube1"),Vector3.up,Quaternion.identity);
		// 下载资源包中的其中一个名字叫Cube2的物体(这个名字一定是在刚才下载的那个包里有的)
		Instantiate(www.assetBundle.Load("Cube2"),Vector3.up,Quaternion.identity);
	}

	// 协同方法,加载一个场景的方法
	IEnumerator LoadScene(string path)
	{
		// 下载已经打包好的场景
		WWW www = new WWW(path + "/scene1.assetbundle");
		yield return www;
		// 获取到包含场景的assetbundle资源包
		AssetBundle bundle = www.assetBundle;
		// 加载的是资源包中的scene1场景,如果没有上面的这行代码,就无法加载这个场景
		Application.LoadLevel("scene1");
	}




	IEnumerator LoadVersion(string path)
	{	
		// 根据版本号加载assetbundle
		WWW www = WWW.LoadFromCacheOrDownload(path + "/Cube1.assetbundle",1);
		yield return www;
		if (www.error != null) {
			print(www.error);
		} else {
			Instantiate(www.assetBundle.mainAsset);
		}
	}


	IEnumerator LoadTex(string path)
	{
		WWW www = new WWW(path + "/Tex1.assetbundle");
		WWW wwwc1 = new WWW(path + "/c1.assetbundle");
		yield return www;
		print(www.assetBundle.mainAsset);
		Instantiate(wwwc1.assetBundle.mainAsset);

	}
}



   
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:920470次
    • 积分:17706
    • 等级:
    • 排名:第551名
    • 原创:180篇
    • 转载:10篇
    • 译文:3篇
    • 评论:46条