1.最近为了精简IOS端的安装包,几乎所有超过5M的资源与模型都放在了服务器上,加载方式为AssetBundle,也方便更新客户后期的修改,功能没问题就没开发啥事儿,改图片或者视频或者模型,让美工部改完了,打AB包上传服务器即可,省事儿!
2.打AB包之前要确定好平台,PC与IOS 不能混用,要区分开。不然加载不出来的,把要打包的资源做成 Prefab并打上标签, 形成资源依赖关系,这样就不会丢失资源了,把Prefab 放到 Assets/Resources/Build 目录下即可。
3.下面上打包代码,打包到处路径为 Assets同级目录 AssetBundle 文件夹下。已加入打包进度与提示,已加入MD5校验。
PS:PC平台 AssetBundle加载不区分字母大小写, IOS平台区分大小写!!! 太坑了,浪费我一天开发时间搞这个(第一次做IOS端AB加载) 建议所有资源都小写命名,(什么驼峰命名,蛇形命名,帕斯卡在这都不中用),加载字符串用 String.ToLower
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
public class AssetBuilder
{
public static List<string> Select()
{
List<string> Selectpaths = new List<string>();
string[] strs = Selection.assetGUIDs;
for (int i = 0; i < strs.Length; i++)
{
var Selectpath = AssetDatabase.GUIDToAssetPath(strs[i]);
Selectpaths.Add(Selectpath);
}
//UnityEngine.Debug.Log("Selectpath:" + Newtonsoft.Json.JsonConvert.SerializeObject(Selectpaths));
return Selectpaths;
}
//[MenuItem("Assets/BuildAssetBundles/ALL")]
public static void BuildOldAssetBundle()
{
#if UNITY_IPHONE
BuildIOS();
BuildPC();
#elif UNITY_STANDALONE_WIN
BuildPC();
BuildIOS();
#endif
}
[MenuItem("Assets/BuildAssetBundles/PC")]
public static void BuildPC()
{
ClearAssetBundlesName();
List<string> data = GetBuildPath();
for (int i = 0; i < data.Count; i++)
SetABName(data[i], Path.GetFileNameWithoutExtension(data[i]));
string paths = Path.GetDirectoryName(Application.dataPath) + "/AssetBundle/win";
if (!Directory.Exists(paths))
Directory.CreateDirectory(paths);
BuildAssetBundle(paths, BuildTarget.StandaloneWindows);
}
[MenuItem("Assets/BuildAssetBundles/IOS")]
public static void BuildIOS()
{
ClearAssetBundlesName();
List<string> data = GetBuildPath();
for (int i = 0; i < data.Count; i++)
SetABName(data[i], Path.GetFileNameWithoutExtension(data[i]));
string paths = Path.GetDirectoryName(Application.dataPath) + "/AssetBundle/ios";
if (!Directory.Exists(paths))
Directory.CreateDirectory(paths);
BuildAssetBundle(paths, BuildTarget.iOS);
}
private static List<string> GetBuildPath()
{
string datapath = Application.dataPath + "/Resources/Build";
DirectoryInfo directoryInfo = new DirectoryInfo(datapath);
var ass = directoryInfo.GetFiles().ToList();
List<string> list1 = new List<string>();
foreach (var item in ass)
{
if (item.Extension != ".meta")
{
string _Path = item.FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets");
UnityEngine.Debug.Log(_Path);
list1.Add(_Path);
}
}
return list1;
}
[MenuItem("Assets/BuildAssetBundles/Clear")]
static void ClearAssetBundlesName()
{
//获取所有的AssetBundle名称
string[] abNames = AssetDatabase.GetAllAssetBundleNames();
//强制删除所有AssetBundle名称
for (int i = 0; i < abNames.Length; i++)
{
AssetDatabase.RemoveAssetBundleName(abNames[i], true);
}
}
/// <summary>
/// 设置单个AssetBundle的Name
/// </summary>
/// <param name="filePath">路径</param>
static void SetABName(string assetPath, string bundlename)
{
//string importerPath = "Assets" + assetPath.Substring(Application.dataPath.Length); //这个路径必须是以Assets开始的路径
AssetImporter assetImporter = AssetImporter.GetAtPath(assetPath); //得到Asset
//string tempName = assetPath.Substring(assetPath.LastIndexOf(@"\") + 1);
//string assetName = tempName.Remove(tempName.LastIndexOf(".")); //获取asset的文件名称
assetImporter.assetBundleName = bundlename;
}
private static void BuildAssetBundle(string Spath, BuildTarget target)
{
BuildPipeline.BuildAssetBundles(Spath, BuildAssetBundleOptions.DeterministicAssetBundle, target);//DeterministicAssetBundle
//刷新编辑器
AssetDatabase.Refresh();
UnityEngine.Debug.Log("打包" + target.ToString() + "资源完成!");
DirectoryInfo info = new DirectoryInfo(Spath);
var files = info.GetFiles("*.manifest", SearchOption.AllDirectories);
for (int i = 0; i < files.Length; i++)
{
files[i].Delete();
}
//SetMd5(Spath);
Process.Start(Spath);
ClearAssetBundlesName();
}
//private static void SetMd5(string spath)
//{
// DirectoryInfo directoryInfo = new DirectoryInfo(spath);
// var files = directoryInfo.GetFiles();
// List<AssBundleInfo> lists = new List<AssBundleInfo>();
// foreach (var item in files)
// {
// if (item.Extension == ".json") continue;
// AssBundleInfo assBundleInfo = new AssBundleInfo();
// assBundleInfo.name = Path.GetFileNameWithoutExtension(item.FullName);
// assBundleInfo.md5 = GetMD5HashFromFile(item.FullName);
// lists.Add(assBundleInfo);
// }
// if (!File.Exists(spath + "/Versions.json"))
// {
// File.Create(spath + "/Versions.json").Close();
// }
// string json = Tools.ObjectToJson(lists);
// File.WriteAllText(spath + "/Versions.json", json);
//}
/// <summary>
/// 获取 MD5 值
/// </summary>
/// <returns> 返回MD5值.</returns>
/// <param name="fileName">文件地址 </param>
private static string GetMD5HashFromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception ex)
{
throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
}
}
}