在最近对AssetBundles打包为.unity3d,发现打包时有些小麻烦,于是就做了一个小工具,由于本人接触的不深入,有很多的不足和考虑不周的地方,希望大侠们多多指教,在这里分享一下。有问题直接留言谈论,我也多多向大侠学习。
现在对于AssetBundles的动态加载资料方法也在博客中有,http://blog.youkuaiyun.com/fanglrui/article/details/9114765可以学习到,在这里就不多说了。
下面是这个编辑窗口,对于窗口编辑在博客中也有相关资料。http://blog.youkuaiyun.com/fanglrui/article/details/9152847
创建文件夹名称:这个就是你所创建的文件夹的名字。路径是在项目文件夹下,例如项目文件名/创建的文件夹名(AssetBundlesPro/AssetBundles)。
要打包的对象名:这个是填写assets里的资源对象,可以是路径。例如:打包对象在resources里面的energy模型。(resources/energy,选择的类型就是.fbx格式)。
保存名称:就是打包的文件名字了。
当然这里可以扩展,比方说扩展出一种配置文件的格式,在打包的时候一块带有自己定制的配置文件。对于这一块由于时间工作的问题没有具体去想。正是这样做的原因是,可以在看得见的情况下去手动输入,减少一些繁琐的事情,当然还有一种做法,很方便。先贴出这个窗口编辑的代码,有不足之处,不妥当的地方,多指教。
using UnityEngine;
using System.Collections;
using System;
using UnityEditor;
/// <summary>
/// 打包为.unity3d格式
/// </summary>
public class ExportUnity3D : EditorWindow
{
/// <summary>
/// 资源对象名称
/// </summary>
private string myTargetPathString = "";
/// <summary>
/// 创建的文件夹名称
/// </summary>
private string mySavePathString = "AssetBundles";
/// <summary>
/// 要保存的文件名称
/// </summary>
private string myFileName = "";
/// <summary>
/// 菜单选择的ID
/// </summary>
private static int typeFileindex;
private static string[] strType = { ".prefab", ".fbx", ".mat", ".tga", ".png", ".cs", ".unity" };
[MenuItem("Window/Export unity3d file")]
static void Init()
{
typeFileindex = 0;
ExportUnity3D exportWindow = (ExportUnity3D)EditorWindow.GetWindow(typeof(ExportUnity3D));
exportWindow.Show();
}
void OnGUI()
{
GUILayout.Label("填写打包为unity3d格式的对象", EditorStyles.boldLabel);
EditorGUILayout.Space();
mySavePathString = EditorGUILayout.TextField("创建文件夹名称(路径):", mySavePathString);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
myTargetPathString = EditorGUILayout.TextField("要打包的对象路径:", myTargetPathString);
typeFileindex = EditorGUILayout.Popup(typeFileindex, strType,GUILayout.Width(65));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
myFileName = EditorGUILayout.TextField("保存名称:", myFileName);
EditorGUILayout.Space();
if (GUILayout.Button("打包"))
{
ExportResource(mySavePathString, myTargetPathString, myFileName);
}
}
/// <summary>
/// 打包方法
/// </summary>
void ExportResource(string path, string filePathName,string fileName)
{
if (path != "" && filePathName != "" && fileName != "")
{
System.IO.Directory.CreateDirectory(path);
BuildAssetBundleOptions options = BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets;
BuildPipeline.PushAssetDependencies();
if (strType[typeFileindex] != ".unity")
{
object asset = AssetDatabase.LoadMainAssetAtPath("Assets/" + filePathName + strType[typeFileindex]);
Debug.Log(asset);
if (asset == null || asset == "Null")
{
this.ShowNotification(new GUIContent(filePathName + strType[typeFileindex] + "-此资源不存在!"));
return;
}
BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/" + filePathName + strType[typeFileindex]), null, path + "/" + fileName + ".unity3d", options);
}
else
{
Debug.Log("Scenec!!!");
string[] str = { "Assets/" + filePathName + strType[typeFileindex] };
//string path = EditorUtility.SaveFilePanel("build bundle", "", "*", "unity3d");
BuildPipeline.BuildStreamedSceneAssetBundle(str, path + "/" + fileName + ".unity3d", BuildTarget.WebPlayerStreamed);
}
this.ShowNotification(new GUIContent(filePathName + strType[typeFileindex] + " -打包成功!!"));
}
else
{
this.ShowNotification(new GUIContent("所填写的内容不能为空!!"));
}
}
}
对于第二种方式,就是在创建和保存时可以自己去选择目录。主要就是这个方法EditorUtility.SaveFilePanel ("Save Resource","","New Resource","unity3d");和EditorUtility.SaveFilePanel ("Save Resource","", "New Resource","unity3d");
具体的方式在http://docs.unity3d.com/Documentation/ScriptReference/BuildPipeline.BuildAssetBundle.html有具体的说明。可以根据上面写成一个窗口的方式,写为窗口的好处就是方便那么一点点。
方便学习,发现了更加方便的打包方式。下面是学习的一些代码,根据自己的需求修改了一下下。这个的原文地址忘记了,属于转载内容。共同学习一下。
using UnityEngine;
using UnityEditor;
using System.IO;
public class Buildunity3d
{
/*
[@MenuItem("Build/AssetBundles PC")]
static void ExportAssetBundles()
{
// Get the selected directory
//获取选择的目录
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
Debug.Log("Selected Folder: " + path);
if (path.Length != 0)
{
path = path.Replace("Assets/", "");
string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);
foreach (string fileName in fileEntries)
{
string filePath = fileName.Replace(" ", "/");
int index = filePath.LastIndexOf("/");
filePath = filePath.Substring(index);
Debug.Log(filePath);
string localPath = "Assets/" + path;
if (index > 0)
//localPath += filePath;
Debug.Log(localPath);
Object t = AssetDatabase.LoadMainAssetAtPath(localPath);
if (t != null)
{
Debug.Log(t.name);
if (!Directory.Exists(Application.dataPath + "/Build"))//判断文件夹是否已经存在
{
Directory.CreateDirectory(Application.dataPath + "/Build");//创建文件夹
}
string bundlePath = "Assets/" + "Build/" + t.name + ".unity3d";
Debug.Log("Building bundle at: " + bundlePath);
// Build the resource file from the active selection.
//从激活的选择编译资源文件
BuildPipeline.BuildAssetBundle
(t, null, bundlePath, BuildAssetBundleOptions.CompleteAssets);
}
}
}
}//*/
[MenuItem("Build/Build AssetBundle From Selection - Track dependencies")]//(包含依耐关系)
static void ExportResource()
{
// Bring up save panel
string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
if (path.Length != 0)
{
// Build the resource file from the active selection.
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets);
Selection.objects = selection;
FileStream fs = File.Open(path + ".log", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("文件 " + path + " 中的内容如下:");
foreach (Object obj in Selection.objects)
{
sw.WriteLine("Name: " + obj.name + "Type:" + obj.GetType());
if (obj.GetType() == typeof(Object)) {
Debug.LogWarning("Name: " + obj.name + ", Type: " + obj.GetType() + ". 可能是unity3d不能识别的文件,可能未被打包成功");
}
}
sw.Flush();
fs.Flush();
sw.Close();
fs.Close();
/*
BuildAssetBundleOptions.CollectDependencies 包含所有依赖关系,应该是将这个物体或组件所使用的其他资源一并打包
BuildAssetBundleOptions.CompleteAssets 强制包括整个资源。例如,如果传递网格到BuildPipeline.BuildAssetBundle函数并使用CompleteAssets,它还将包括游戏物体和任意动画剪辑,在同样的资源。
应该是,下载一部分,其余一并下载
BuildAssetBundleOptions.DisableWriteTypeTree 禁用写入类型树,在资源包不包含类型信息。指定这个标识将使资源包易被脚本或Unity版本改变,但会使文件更小,更快一点加载。这个标识只影响默认包含的类型信息的平台资源包。
BuildAssetBundleOptions.DeterministicAssetBundle 确定资源包,编译资源包使用一个哈希表储存对象ID在资源包中。
这使您可以重建的资产包,并直接引用资源。当重建资源包对象,在重建之后保证有相同的ID。由于它是一个32位的哈希表空间,如果在资源包有许多对象,这将增加潜在哈希表冲突。
Unity将给出一个错误,而不在这种情况下编译。哈希表是基于资源的GUID和对象的自身ID。
DeterministicAssetBundle加载被标准资源包慢,这是因为线程后台加载API通常期望对象排序的方式,这会使读取加少寻址。
*/
//GC
System.GC.Collect();
}
}
[MenuItem("Build/Build AssetBundle From Selection - No dependency tracking")]//(不包含依耐关系)
static void ExportResourceNoTrack()
{
// Bring up save panel
string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
if (path.Length != 0)
{
// Build the resource file from the active selection.
BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path, BuildAssetBundleOptions.CompleteAssets, BuildTarget.StandaloneWindows);
FileStream fs = File.Open(path + ".log", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("文件 " + path + " 中的内容如下:");
foreach (Object obj in Selection.objects)
{
sw.WriteLine("Name: " + obj.name + "Type: " + obj.GetType());
if (obj.GetType() == typeof(Object)) {
Debug.LogWarning("Name: " + obj.name + ", Type: " + obj.GetType() + ". 可能是unity3d不能识别的文件,可能未被打包成功");
}
}
sw.Flush();
fs.Flush();
sw.Close();
fs.Close();
}
//GC
System.GC.Collect();
}
//------------------------------------------------------------------------------------------------------------------
//单独打包文件夹中的每个文件为*.unity3d文件,放在原来的位置
[MenuItem("Build/Build AssetBundles From Directory of Files")]
static void ExportAssetBundleEachfile2Path()
{
//在项目视图从选择的文件夹生成资源包
//记住,这个函数不跟踪依赖关系,也不是递归
// Get the selected directory
//获取选择的目录
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string unity3dFileName;
Debug.Log("Selected Folder: " + path);
if (path.Length != 0)
{
int pos = path.LastIndexOf('/');
if (pos == -1)
{
return;
}
unity3dFileName = path.Substring(pos + 1, path.Length - pos - 1);
Debug.Log("unity3dFileName: " + unity3dFileName);
path = path.Replace("Assets/", "");
string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);
foreach (string fileName in fileEntries)
{
string filePath = fileName.Replace(" ", "/");
int index = filePath.LastIndexOf("/");
filePath = filePath.Substring(index);
Debug.Log(filePath);
string localPath = "Assets/" + path;
if (index > 0)
//localPath += filePath;
Debug.Log(localPath);
Object t = AssetDatabase.LoadMainAssetAtPath(localPath);
if (t != null)
{
Debug.Log(t.name);
//string bundlePath = "Assets/" + path + "/" + t.name + ".unity3d";
string pathSelect = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
Debug.Log("Building bundle at: " + pathSelect);
// Build the resource file from the active selection.
//从激活的选择编译资源文件
BuildPipeline.BuildAssetBundle
(t, null, pathSelect, BuildAssetBundleOptions.CompleteAssets);
}
}
}
//GC
System.GC.Collect();
}
[MenuItem("Build/Build AssetBundles by Directory")]
static void ExportAssetBundleByDirectory()
{
//一次选择多个文件夹,分别打包,生成的unity3d文件按文件夹名字命名且放在文件夹中,同时生成.log文件
int dirs = Selection.objects.Length, i;
string[] filters = new string[]{//过滤不打包的文件类型
".unity3d",".log",".db",};
for (i = 0; i < dirs; i++)//处理所选文件夹
{
string path = AssetDatabase.GetAssetPath(Selection.objects[i]);
string unity3dFileName;
if (path.Length != 0)
{
int pos = path.LastIndexOf('/');
if (pos < 0) pos = 0;
unity3dFileName = path.Substring(pos);
//获取文件列表
string[] fileEntries = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);//仅本级目录
//过滤文件类型
int size = 0;
bool[] enable = new bool[fileEntries.Length];
for (int how = 0; how < fileEntries.Length; how++)
{
bool filterFlag = false;
foreach (string s in filters)
{
if (fileEntries[how].EndsWith(s, System.StringComparison.OrdinalIgnoreCase))
{
filterFlag = true;
break;
}
}
enable[how] = filterFlag;
if (!filterFlag) size++;
}
if (size != 0)
{
Object[] objects = new Object[size];
//载入文件
int id = 0;
for (int k = 0; k < fileEntries.Length; k++)
{
if (enable[k] == false)
{
string fileName = fileEntries[k];
string localPath = fileName.Replace("", "/");
objects[id] = AssetDatabase.LoadMainAssetAtPath(localPath);//AssetDatabase.LoadAllAssetsAtPath不知为何不能用?
id++;
}
}
//打包
if (id != 0)
{
string str = path + unity3dFileName + ".unity3d";
BuildPipeline.BuildAssetBundle(objects[0], objects, str, BuildAssetBundleOptions.CompleteAssets, BuildTarget.StandaloneWindows);
FileStream fs = File.Open(path + unity3dFileName + ".log", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("文件 " + str + " 中的内容如下:");
foreach (Object obj in objects)
{
sw.WriteLine("Name: " + obj.name + "Type: " + obj.GetType());
if (obj.GetType() == typeof(Object))
{
Debug.LogWarning("Name: " + obj.name + ", Type: " + obj.GetType() + ". 可能是unity3d不能识别的文件,可能未被打包成功");
}
}
sw.Flush();
fs.Flush();
sw.Close();
fs.Close();
Debug.Log("打包成功! " + str);
}
else
{
Debug.LogError("没有可打包的文件! 目录:" + path);
}
}
else
{
Debug.LogError("没有可打包的文件! 全部被过滤, 目录:" + path);
}
}
}
//GC
System.GC.Collect();
}
}