前言:
熱更的話現在有很多流行的方式,xlua了等,這裏我只對資源這一部分進行簡單介紹,assetbundle的服務器下載和使用流程,代碼的更新後續在更
首先,打包的比較簡單不過多贅述。這裏我保存了一下資源的依賴關係,並且把存儲的依賴關係存儲到了項目中,一塊打包。然後當我們使用assetbundle的時候,根據依賴關係進行download就可了。這一點一定要記得,因爲一開始想着從服務器下載存放bundle的整個文件夾,然後去讀取,後來發現過於繁瑣,而且不易實現,最後發現應該是使用一個表一樣的,根據需求去下在對應的bundle,然後去獲取資源就可以, ,沒必要在單獨存儲。
首先我們需要進行bundle tag設置,並將依賴,場景關係保存 這樣我們可以吧不同的場景打入不同的包體,減小包體大小,下載也能更快
public static void SetBundleName()
{
//移除未使用的 tag
AssetDatabase.RemoveUnusedAssetBundleNames();
if (!Directory.Exists(ConfigSetting.SourcePath))
{
Debug.LogError("不存在該路徑");
return;
}
DirectoryInfo dir = new DirectoryInfo(ConfigSetting .SourcePath );
FileSystemInfo[] infos = dir.GetFileSystemInfos();
for (int i = 0; i < infos .Length ; i++)
{
FileSystemInfo info = infos[i];
if (info is DirectoryInfo)
{
string path = ConfigSetting.SourcePath + info.Name;
SetFodlerFiles(path,info .Name );
}
}
}
/// <summary>
/// 設置整個文件夾內的文件
/// </summary>
/// <param name="path"></param>
private static void SetFodlerFiles(string path,string fodlername )
{
Debug.Log("資源路徑:" + path);
string savepath = ConfigSetting.BuildPath + fodlername;
if(!Directory .Exists (savepath))
{
Directory.CreateDirectory(savepath);
}
//創建讀寫流
FileStream fs = new FileStream(savepath +"/" + fodlername+".txt", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
//存儲關聯關係
Dictionary<string, string> dic_Infos = new Dictionary<string, string>();
ChangeHead(path, dic_Infos);
sw.WriteLine(dic_Infos.Count);//行數
foreach (var item in dic_Infos )
{
sw.Write(item.Key);
sw.Write("*");
sw.Write(item.Value);
sw.WriteLine();
}
//使用流結束關閉
sw.Close();
fs.Close();
}
/// <summary>
/// 獲取相對路徑 D:/ZIZOUQI/Project/Assets/_Source/obj.u3d
/// </summary>
private static void ChangeHead(string fullpath,Dictionary<string, string> dic_Infos)
{
Debug.Log("fullpath:" + fullpath);// F:/U3D/HotFit/Assets/_Source/
//得到的是 F:/U3D/HotFit/的長
int count = fullpath.IndexOf("Assets");
int length = fullpath.Length;
string replacepath = fullpath.Substring(count, length - count);
Debug.Log("replacepath:" + replacepath);// Assets/_Source/
DirectoryInfo dir = new DirectoryInfo(fullpath);
if (dir != null)
{
ListFiles(dir, replacepath,dic_Infos);
}
else
{
Debug.LogError("不存在路徑:" + fullpath);
}
}
/// <summary>
/// 遍歷文件夾
/// </summary>
/// <param name="info"></param>
/// <param name="replacepath"></param>
/// <param name="dic"></param>
private static void ListFiles(FileSystemInfo info,string replacepath,Dictionary <string ,string> dic)
{
if (!info.Exists)
{
Debug.Log("不存在文件" + replacepath);
return;
}
FileSystemInfo[] files = (info as DirectoryInfo ).GetFileSystemInfos();
for (int i = 0; i < files .Length ; i++)
{
FileInfo file = files[i] as FileInfo;
//操作文件
if (file != null)
{
// Assets/_Source/
ChangeMark(file, replacepath, dic);
}else
//操作目錄
{
ListFiles(files[i], replacepath, dic);
}
}
}
/// <summary>
/// 改變tag
/// </summary>
/// <param name="temp"></param>
/// <param name="replacepath"></param>
/// <param name="dic"></param>
private static void ChangeMark(FileInfo temp,string replacepath,Dictionary<string ,string> dic)
{
if (temp .Extension == ".meta")
{
return;
}
Debug.Log("文件路徑:"+replacepath);//Assets/_Source/
string markStr = GetBundlePath(temp, replacepath);
SetTag(temp,markStr, dic);
}
private static string GetWindowsPath(string path)
{
path =path .Replace ("\\","/");
return path;
}
/// <summary>
/// 計算標記值
/// </summary>
/// <param name="file"></param>
/// <param name="replacepath"></param>
/// <returns></returns>
public static string GetBundlePath(FileInfo file,string replacepath)
{
string path = GetWindowsPath(file.FullName);
//Debug.Log("windows:" + path);//F:/U3D/HotFit/Assets/_Source/TEST/New Folder/Cube.prefab
int length = path.IndexOf(replacepath);
//Debug.Log("length" + length);
length += replacepath.Length+1;//replacepath Assets/_Source/
//Debug.Log("length" + length);
int namelength = path.LastIndexOf(file.Name);
int templength = replacepath.LastIndexOf("/");
string sceneHead = replacepath.Substring(templength +1,replacepath .Length -templength -1);
Debug.Log("head:" + sceneHead);
if (namelength -length > 0)
{
string substring = path.Substring(length,path .Length -length);
string[] result = substring.Split('/');
Debug.Log("result:" + result[0]);
return sceneHead+"/"+ result[0];
}else
{
return sceneHead;
}
}
private static void SetTag(FileInfo file, string tag, Dictionary<string, string> dic)
{
Debug.Log("設置文件標籤:" + file.Name+" TAG:"+tag );
int assetcount = file.FullName.IndexOf("Assets");
string path = file.FullName.Substring(assetcount, file.FullName.Length - assetcount);
AssetImporter imp = AssetImporter.GetAtPath(path);
imp.assetBundleName = tag;
if (file.Extension == ".unity")
{
imp.assetBundleVariant = "u3d";
} else
{
imp.assetBundleVariant = "ld";
}
string name = null;
string[] subs = tag.Split('/');
if (subs.Length > 1)
{
name = subs[1];
} else
{
name = tag;
}
string assetpath = tag.ToLower() + "." + imp.assetBundleVariant;
if (!dic.ContainsKey(name))
{
Debug.Log("key:"+name +" value:"+assetpath );
dic.Add(name, assetpath);
}
}
這個比較複雜,進行了一系列的計算轉化的,就是爲了映射你的資源目錄zeya
好,放打包腳本,該方法是編輯器擴展方法,頭文件沒放,可以自行添加
/// <summary>
/// 打包
/// </summary>
/// <param name="target"></param>
private static void Build(BuildPlat plat,BuildTarget target)
{
string path = ConfigSetting.BuildPath + plat.ToString() + "/";
if(!Directory .Exists (path))
{
Directory.CreateDirectory(path);
}
Debug.Log("打包路徑:" + path);
BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.ChunkBasedCompression, target);
Debug.Log("打包完成");
AssetDatabase.Refresh();//刷新文件
}
當設置了tag,並打包後,會輸出打包完成。並且會在streamingasset下生產對應的文件夾 以win64爲例,打開後內容如下,如果出現說明完成打包。
接下來是上傳文件到服務器,我們採取http協議,使用hfs 進行測試。hfs是一個輕量級的文件服務器,不需要安裝,雙擊運行就行了
然後關於下載,要首先下載win64bundle,獲取manifest文件,然後讀取項目中的配置文件,根據對應的路徑進行資源加載
bundle下載:
UnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle(manifestPath);
yield return req.SendWebRequest();
while (req.downloadProgress < 1.0f)
{
yield return null;
}
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(req);
assetmanifest = bundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
讀取配置文件
/// <summary>
/// 讀取配置文件
/// </summary>
/// <param name="filename"></param>
public void ReadConfigFile()
{
string PATH = ConfigSetting.OutSourcePath+manager .SceneName +".txt";
Debug.Log("配置信息 path:" + PATH);
FileStream fs = new FileStream(PATH, FileMode.Open);
StreamReader sr = new StreamReader(fs);
int linecount = int.Parse(sr.ReadLine());
for (int i = 0; i < linecount; i++)
{
string[] data = sr.ReadLine().Split ('*');
Debug.Log("bundlename:"+data [0] + " bundle:" + data [1]);
allAsset.Add(data[0], data[1]);
}
sr.Close();
fs.Close();
}
經過測試確實是可以的,有問題歡迎來諮