diff options
Diffstat (limited to 'Assets/Scripts/ResManager.cs')
-rw-r--r-- | Assets/Scripts/ResManager.cs | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/Assets/Scripts/ResManager.cs b/Assets/Scripts/ResManager.cs new file mode 100644 index 0000000..ba47f8e --- /dev/null +++ b/Assets/Scripts/ResManager.cs @@ -0,0 +1,273 @@ +using System.Collections; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.IO; +using UnityEngine; +using UnityEngine.UI; +using MEC; + +public class ResManager { + + private struct BundleInfo{ + public long size; + public string hash; + } + + public static ResManager Instance + { + get + { + if (_instance == null) + _instance = new ResManager(); + return _instance; + } + } + static ResManager _instance; + + Test test; + string Content; + + static string BundleRoot = "PackData"; + static string ManifestBundleName = "PackData"; + static string ManifestFileResName = "bundles"; // under Resources/bundles.manifest + static string ManifesteRemotePath = "bundles.manifest"; +#if UNITY_STANDALONE_WIN + static string cdnAddress = "http://localhost/bundles/"; // PC +#elif UNITY_ANDROID + static string cdnAddress = "http://10.0.2.2/bundles/"; // AndroidEmu +#endif + + Dictionary<string, AssetBundle> CachedBundles = new Dictionary<string, AssetBundle>(); + Dictionary<string, string> FileMapping = new Dictionary<string, string>(); + AssetBundleManifest Manifest; + +#region 更新相关 + // 本地streamingAssetsPath下的bundles数据,从固化的bundles.manifest中读取 + Dictionary<string, BundleInfo> localBundles = new Dictionary<string, BundleInfo>(); + // CDN上的bundles数据 + Dictionary<string, BundleInfo> remoteBundles = new Dictionary<string, BundleInfo>(); +#endregion + + public void Init(Test test) + { + this.test = test; + LoadLocalBundlesInfo(); + Timing.Instance.RunCoroutineOnInstance(DownloadManifest()); + } + + void Print(string content , bool alert = false) + { + test.Print(content, alert); + } + + public string ResContent(string path) + { + TextAsset text = Resources.Load(path) as TextAsset; + if (text == null) + return null; + return text.text; + } + + public void ReadFileMapping() + { + AssetBundle bundle = LoadBundle("bundle00.ab"); // 不可以省略后缀 + if (bundle == null) + { + string path = PathHelper.GetStreamingFullFilePath(BundleRoot + "/bundle00.ab"); + Print("Bundle 为空, path = " + path, true); + return; + } + TextAsset text = bundle.LoadAsset<TextAsset>("fileMapping"); + if (text == null) + return; + string content = text.text; + content = content.Replace("\r", string.Empty); + string[] lines = content.Split('\n'); + Print("Load FileMapping:"); + foreach (string line in lines) + { + string[] part = line.Split(','); + FileMapping.Add(part[0], part[1]); + Print(part[0] + " " + part[1]); + } + } + + /// <summary> + /// 刚开始进入游戏的时候要写入.manifest,用来后续对比更新 + /// </summary> + public void LoadManifest() + { + AssetBundle bundle = LoadBundle(ManifestBundleName); + if (bundle == null) + { + Print("没有Manifest", true); + return; + } + Manifest = bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); + if (Manifest == null) + { + Print("AssetBundleManifest", true); + return; + } + Print("All bundles:"); + string[] bundleNames = Manifest.GetAllAssetBundles(); + foreach (var bundleName in bundleNames) + { + Print(bundleName); + } + } + + public AssetBundle LoadBundle(string name) + { + AssetBundle bundle; + if (CachedBundles.TryGetValue(name, out bundle)) + { + return bundle; + } + string path = PathHelper.GetPersistentFullFilePath(BundleRoot + "/" + name); + Print(path); + if (!File.Exists(path)) + { + Print("不在persistent里"); + path = PathHelper.GetStreamingFullFilePath(BundleRoot + "/" + name); + } + bundle = AssetBundle.LoadFromFile(path); + if(bundle == null) + Print("是空的"); + CachedBundles.Add(name, bundle); + return bundle; + } + + public string GetBundleName(string assetName) + { + string bundleName; + FileMapping.TryGetValue(assetName, out bundleName); + return bundleName; + } + + public string BundleContent(string resName) + { + string bundleName = GetBundleName(resName); + if (bundleName == null) + return null; + AssetBundle bundle = LoadBundle(bundleName); + if (bundle == null) + return null; + TextAsset text = bundle.LoadAsset<TextAsset>(resName); + if (text == null) + return null; + return text.text; + } + + /// <summary> + /// 根据Resources/bundles.manifest读取本地bundle数据 + /// </summary> + private void LoadLocalBundlesInfo() + { + TextAsset manifest = Resources.Load<TextAsset>(ManifestFileResName); + if(manifest == null) + { + Debug.LogError("本地Resources目录下没有bundles.manifest"); + return; + } + string[] bundles = manifest.text.Replace("\r", string.Empty).Split('\n'); + string[] info; + foreach(string bundle in bundles) + { + info = bundle.Split(','); + if (info.Length != 3) + continue; + BundleInfo bi = new BundleInfo(); + bi.size = long.Parse(info[1]); + bi.hash = info[2]; + localBundles.Add(info[0], bi); + } + } + + IEnumerator<float> DownloadManifest() + { + WWW www = new WWW(cdnAddress + ManifesteRemotePath); + while(!www.isDone) + { + yield return Timing.WaitForSeconds(0.01f); + } + string content = www.text; + string[] bundles = content.Replace("\r", string.Empty).Split('\n'); + string[] info; + foreach (string bundle in bundles) + { + info = bundle.Split(','); + if (info.Length != 3) + continue; + BundleInfo bi = new BundleInfo(); + bi.size = long.Parse(info[1]); + bi.hash = info[2]; + remoteBundles.Add(info[0], bi); + } + // Download bundles + Timing.Instance.RunCoroutineOnInstance(DownloadBundles()); + } + + IEnumerator<float> DownloadBundles() + { + List<string> downloadBundles = new List<string>(); + foreach(var b in remoteBundles) + { + string bundleName = b.Key; + long size = b.Value.size; + string hash = b.Value.hash; + BundleInfo localInfo; + //1. 剔除首包中就有的 + if (localBundles.TryGetValue(bundleName, out localInfo) && localInfo.hash == hash) + continue; + //2. 剔除上次小版本更新下载下来的 + string persistentPath = PathHelper.GetPersistentFullFilePath(BundleRoot + "/" + bundleName); + if(File.Exists(persistentPath)) + { + long lastsize = new FileInfo(persistentPath).Length; + if(lastsize == size) + { + string lasthash = FileUtil.GetMD5Hash(persistentPath); + if (lasthash == "") + { + Debug.LogError("计算md5出错"); + } + else if (lasthash == hash) + continue; + } + } + downloadBundles.Add(bundleName); + } + //3. 下载 + foreach (string bundle in downloadBundles) + { + WWW www = new WWW(cdnAddress + bundle); + while(!www.isDone) + { + yield return Timing.WaitForSeconds(0.01f); + } + // save to persistentDataPath + Print("->下载" + bundle + "完毕"); + byte[] data = www.bytes; + string folder = PathHelper.GetPersistentFullFilePath(BundleRoot); + if (!Directory.Exists(folder)) + Directory.CreateDirectory(folder); + File.WriteAllBytes(folder + "/" + bundle, data); + } + + Print("Bundle 下载完毕,共下载" + downloadBundles.Count + "个"); + Print("------------------------------------------------------------------------"); + // test test + ResManager.Instance.ReadFileMapping(); + ResManager.Instance.LoadManifest(); + // Done + OnDownloaded(); + } + + void OnDownloaded() + { + if (test != null) + test.Testing(); + } + +} |