http://www.manew.com/thread-42925-1-1.html 一直搞不明白四种力模式的区别,百度下了下,觉得分析的很透彻,分享给大家 ForceMode为枚举类型,用来控制力的作用方式,有4个枚举成员,在以下举例中均设刚体质量为m=2.0f,力向量为f=(10.0f,0.0f,0.0f)。 (1)ForceMode.Force:默认方式,使用刚体的质量计算,以每帧间隔时间为单位计算动量。设FixedUpdate()的执行频率采用系统默认值(即0.02s),,则由动量定理 f•t=m•v 可得:10*0.02=2*v1,从而可得v1=0.1,即每帧刚体在X轴上值增加0.1米,从而可计算得刚体的每秒移动速度为v2=(1/0.02)*v1=5m/s。 (2)ForceMode.Acceleration:在此种作用方式下会忽略刚体的实际质量而采用默认值1.0f,时间间隔以系统帧频间隔计算(默认值为0.02s),即 f•t=1.0•v 即可得v1= f•t=10*0.02=0.2,即刚体每帧增加0.2米,从而可得刚体的每秒移动速度为v2=(1/0.02)*v1=10m/s。 (3)ForceMode.Impulse:此种方式采用瞬间力作用方式,即把t的值默认为1,不再采用系统的帧频间隔,即 f•1.0=m•v 即可得v1=f/m=10.0/2.0=5.0,即刚体每帧增加5.0米,从而可得刚体每秒的速度为v2=(1/0.02)*5.0=250m/s。 (4)ForceMode.VelocityChange:此种作用方式下将忽略刚体的实际质量,采用默认质量1.0,同时也忽略系统的实际帧频间隔,采用默认间隔1.0,即 f•1.0=1.0•v 即可得v1=f=10.0,即刚体每帧沿X轴移动距离为10米,从而可得刚体每秒的速度为v2=(1/0.02)*v1=500m/s using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using SimpleJson; //using System; /// <summary> /// 1、加载Document目录中的资源, /// 分为dll代码和一个prefab的assetBundle /// code通过getComponent累进行动态获取, /// 更新的prefab通过从assetBundle中加载 /// </summary> public class LocalResourceManager : MonoBehaviour { private static LocalResourceManager instance; //需要更新的资源直接是一行一个需要更新的资源,格式为:资源名#资源大小#资源名称|资源名称|资源名称 public static readonly string UPDATE_RES_LIST = "updateResList.txt"; //需要更新的所有的dll public static readonly string Dll_VERSION_FLIE = "lxxc_dll.unity3d"; //更新的prefab public static readonly string AB_VERSION_FLIE = "updatePrefab.unity3d"; //protobuff 加密协议 public static readonly string PROTO_BUFF = "protobuff.txt"; public static readonly string BATTLE_MONST_DATA = "BattleDemoMonsterData.txt"; public static readonly string BATTLE_DATA = "BattleDemoBattleData.txt"; public static readonly string BATTLE_PLAYER_DATA = "BattleDemoPlayerData.txt"; public delegate void HandleFinishDownload (WWW www); private static string LOCAL_RES_PATH = ""; public DownLoadMananger.DownLoadResProgress downloadProgress; public DownLoadMananger.DownFinish updateFinish; //已经加载好的数据库数据 [HideInInspector] public byte[] dbBytes; public byte[] dbCompressBytes; private List<string> loadResource; //更新的assembly private static Assembly assembly; private AssetBundle prefabAb; private List<string> bundleList; private static bool isFinish = false; /// <summary> /// 获取ResourceUpdate单例对象 /// </summary> /// <returns>The instance.</returns> public static LocalResourceManager GetInstance () { return instance; } // Use this for initialization void Awake () { instance = this; } // Update is called once per frame void Update () { } //下载更新资源 public void LoadedDocumentRes () { if (isFinish) { if (updateFinish != null) { updateFinish (); } return; } //加载bundle的配置文件 DownLoadMananger.GetInstance ().InitParam (); string filePath = GameUtils.GetAssetPath () + BundleManager.BundleConfigFileName; DownLoadMananger.GetInstance ().downLoadOneFinish = loadBundleCfgOneFinish; DownLoadMananger.GetInstance ().downFinish = LoadBundleCfgFinish; List<string> list = new List<string> (); list.Add (filePath); DownLoadMananger.GetInstance ().StartDownLoad (list); } void loadBundleCfgOneFinish (string fileName, WWW wwwData) { BundleManager.GetInstance ().SetConfigData (wwwData.text); } void LoadBundleCfgFinish () { LOCAL_RES_PATH = GameUtils.GetDocumentsPath () + "/"; string result = GetOldUpdateList (); bundleList = BundleManager.GetInstance ().GetBundleUrlList (); if (loadResource == null) { loadResource = new List<string> (); } loadResource.AddRange (bundleList); if (result != "") { string[] items = result.Split (new char[] { '\n' }); for (int i = 0; i < items.Length; i++) { if (items [i] != "") { loadResource.Add (LOCAL_RES_PATH + items [i]); } } } loadResource.AddRange (InitBattleDemoData()); DownLoadMananger.GetInstance ().InitParam (); DownLoadMananger.GetInstance ().downFinish = LoadFinish; DownLoadMananger.GetInstance ().downLoadOneFinish = DownLoadOneFinish; DownLoadMananger.GetInstance ().downLoadProgress = downloadProgress; DownLoadMananger.GetInstance ().StartDownLoad (loadResource); } List<string> InitBattleDemoData(){ List<string> path = new List<string> (); path.Add (GameUtils.getPersistentPath() + "BattleDemo/" + BATTLE_MONST_DATA); path.Add (GameUtils.getPersistentPath() + "BattleDemo/" + BATTLE_DATA); path.Add (GameUtils.getPersistentPath() + "BattleDemo/" + BATTLE_PLAYER_DATA); return path; } void LoadFinish () { isFinish = true; SQLiteDataManager.GetInstance ().finishCallback = updateFinish; LoginLoadingView.GetInstance ().SetLoadText ("正在解压配置,请稍等...."); SQLiteDataInit.GetInstance ().InitSQLiteData (); } void DownLoadOneFinish (string fileName, WWW wwwData) { //将下载的资源替换本地就的资源 if (fileName.IndexOf (Dll_VERSION_FLIE) >= 0) { LoadAssembly (wwwData); return; } if (fileName.IndexOf (SQLiteDataInit.DBEncodeFileName) >= 0) { dbBytes = wwwData.bytes; } else if (fileName.IndexOf (SQLiteDataInit.DBCompressFileName) >= 0) { dbCompressBytes = wwwData.bytes; } else if (fileName.IndexOf (AB_VERSION_FLIE) >= 0) { prefabAb = wwwData.assetBundle; } else if (fileName.IndexOf (PROTO_BUFF) >= 0) { Pomelo.DotNetClient.Protocol.protoBuffJson = (JsonObject)SimpleJson.SimpleJson.DeserializeObject (wwwData.text); } else if (fileName.IndexOf (BATTLE_DATA) >= 0) { GLogger.Log (wwwData.text); BattleDemoManager.battleData = wwwData.text; } else if (fileName.IndexOf (BATTLE_MONST_DATA) >= 0) { BattleDemoManager.battleMonstData = wwwData.text; } else if (fileName.IndexOf (BATTLE_PLAYER_DATA) >= 0) { GLogger.Log (wwwData.text); BattleDemoManager.battlePlayerData = wwwData.text; } //设置boundle for (int i = 0; i < bundleList.Count; i++) { if (bundleList [i].IndexOf (fileName) >= 0) { BundleManager.GetInstance ().SetBoundle (fileName, wwwData); } } } string GetOldUpdateList () { string path = LOCAL_RES_PATH.Replace ("file://", "") + UPDATE_RES_LIST; CreateDic (path); return GetFileContent (path); } //创建路径 void CreateDic (string filePath) { int index = filePath.LastIndexOf ('/'); string dir = filePath.Substring (0, index + 1); if (!Directory.Exists (dir)) { Directory.CreateDirectory (dir); } } //给物体上挂在脚本 public void AddComponentToResource (string className, GameObject gb) { System.Type type = assembly.GetType (className); if (type == null) { Assembly assembly2 = Assembly.GetAssembly (typeof(ResourceUpdate)); type = assembly2.GetType (className); } // GLogger.Log (type + "***************额额额额额***************************************************" + className); if (gb != null && type != null && gb.GetComponent (type) == null) { gb.AddComponent (type); } } //加载并存储code private void LoadAssembly (WWW assemblyBytes) { if (assemblyBytes == null) { return; } //iphone #if UNITY_IPHONE || UNITY_IOS || UNITY_IPHONE_API Assembly[] array = System.AppDomain.CurrentDomain.GetAssemblies (); for (int i = 0; i < array.Length; i++) { if(array[i].FullName.IndexOf("lxxc_dll") >= 0){ assembly = array[i]; break; } } #endif #if UNITY_ANDROID AssetBundle bundle = assemblyBytes.assetBundle; string loadName = Dll_VERSION_FLIE.Substring (0, Dll_VERSION_FLIE.LastIndexOf ('.')); TextAsset asset = bundle.Load (loadName, typeof(TextAsset)) as TextAsset; assembly = System.Reflection.Assembly.Load (asset.bytes); #endif // //使用当前程序集中的类 // #if UNITY_EDITOR // assembly = Assembly.GetAssembly (typeof(ResourceUpdate)); // #endif //使用其他加载进来的dll中的类 #if UNITY_EDITOR string sapath = Application.streamingAssetsPath; string BinPath = sapath.Substring (0, sapath.IndexOf ("lxxc")); assembly = Assembly.LoadFile (BinPath + "lxxc_dll/obj/Debug/lxxc_dll.dll"); #endif // System.Type[] types = assembly.GetExportedTypes(); // for (int i = 0; i < types.Length; i++) { // GLogger.Log(types[i].Name + "**************"); // // } assemblyBytes.Dispose (); } // public AssetBundle HasInNewPrefab (string assetName) { if (prefabAb == null) { return null; } if (prefabAb.Contains (assetName)) { return prefabAb; } return null; } string GetFileContent (string path) { if (!File.Exists (path)) { return ""; } StringBuilder sb = new StringBuilder (); StreamReader sr = new StreamReader (path, Encoding.Default); string line; while ((line = sr.ReadLine ()) != null) { sb.Append (line + "\n"); } sr.Close (); return sb.ToString (); } } using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System; //using System; /// <summary> /// 1、从服务器获取版本号,和当前客户端存储的版本号进行对比, /// a、如果相同则不更新 /// b、如果不同,则从服务器获取需要更新的资源列表文件version.txt,再没有进行大版本更新的时候,这个列表是进行累加的。; /// c、文件更新后,修改客户端本地的版本号存储到version.txt文件中。 /// </summary> /// /// <summary> /// 1.在vs中新建一个代码库工程,命名为test //2.添加几个类Scirpt,Scirpt2,Data //3.将这个项目生成DLL,test.dll //4.新建一个unity项目,将DLL倒入到Asset,改名为test.bytes,不然可能会报错 //5.利用我们之前实现过的打包脚本,将test.bytes打包成test.assetbundle。 //6.创建CodeUpdate.cs脚本,用于加载代码资源,反射调用。 //7.为了验证代码更新后,可以直接加载使用,我们可以更改一下Data.cs的代码,重复以上过程,可以看到,更新了代码打包后,我们重新运行游戏,就可以看到效果 /// </summary> public class ResourceUpdate : MonoBehaviour { private static ResourceUpdate instance; //需要更新的资源直接是一行一个需要更新的资源,格式为:资源名#资源大小#资源名称|资源名称|资源名称 public static readonly string UPDATE_RES_LIST = "updateResList.txt"; //本地存储版本号 public static readonly string LOCAL_VERSION = "version.txt"; //需要更新的所有的dll public static readonly string Dll_VERSION_FLIE = "lxxc_dll.unity3d"; //格式为:资源名(为更新的资源名)#GameObject.name_c#clssName_GameObject.name_c#clssName public static readonly string Dll_TO_RES_VERSION_FLIE = "dynamicRes.txt"; public static string LOCAL_RES_URL = ""; public static string SERVER_RES_URL = ""; public static string LOCAL_RES_PATH = ""; public delegate void HandleFinishDownload (WWW www); private static List<string> localResVersion; private static List<string> totalUpdateResList; //格式为:资源名, GameObject.name_c#clssName_GameObject.name_c#clssName; private Dictionary<string, string> dll2Res; private System.Reflection.Assembly assembly; public DownLoadMananger.DownFinish updateFinish; public DownLoadMananger.DownLoadResProgress downloadProgress; //下载版本文件,解析成功后回调 public delegate void ParseUpdateListCallback (); public ParseUpdateListCallback parseFinishCallBack; //本次更新资源总大小 public static float updateTotalSize; //是否需要更新db public static bool isUpdateDB = false; //是否下载完成 public static bool isDownloaded = true; //当前下载的文件进度 public static float currentDownNum = 0f; private int totalNum = 1; public static WWW currentWWW; /// <summary> /// 获取ResourceUpdate单例对象 /// </summary> /// <returns>The instance.</returns> public static ResourceUpdate GetInstance () { return instance; } // Use this for initialization void Awake () { LOCAL_RES_PATH = GameUtils.GetDocumentsPath () + "/"; LOCAL_RES_URL = GameUtils.GetDocumentsPath () + "/"; instance = this; localResVersion = new List<string> (); totalUpdateResList = new List<string> (); GLogger.Log (Application.dataPath + "==========" + LOCAL_RES_URL); } void InitUpdateList () { if (SERVER_RES_URL != "") { return; } ResetServerPath (); string result = GetOldUpdateList (); if (result != "") { string[] items = result.Split (new char[] { '\n' }); totalUpdateResList = new List<string> (items); } } void ResetServerPath () { SERVER_RES_URL = GlobalConfig.ResUrl; #if UNITY_EDITOR SERVER_RES_URL += "android/"; #elif UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX SERVER_RES_URL += "pc/"; #elif UNITY_IPHONE || UNITY_IOS || UNITY_IPHONE_API SERVER_RES_URL += "ios/"; #elif UNITY_ANDROID SERVER_RES_URL += "android/"; #endif } // Update is called once per frame void Update () { } //下载更新资源 public void DownloadServerVersionTxt () { NetDataRequestTip.showLoading (); isDownloaded = false; InitUpdateList (); updateTotalSize = 0; //先下载资源更新的列表文件 DownLoadMananger.GetInstance ().InitParam (); DownLoadMananger.GetInstance ().downLoadOneFinish = DownLoadUplistFinish; DownLoadMananger.GetInstance ().downFinish = DownUpdateListFinish; List<string> list = new List<string> (); list.Add (SERVER_RES_URL + UPDATE_RES_LIST + "?time=" + System.DateTime.Now.Ticks); DownLoadMananger.GetInstance ().StartDownLoad (list); } void DownLoadUplistFinish (string file, WWW wwwData) { NetDataRequestTip.removeLoading (); ParseVersionFile (wwwData.text, localResVersion); } void DownUpdateListFinish () { if (parseFinishCallBack != null) { parseFinishCallBack (); } } public int GetTotalDownNum () { return totalNum; } //依次加载需要更新的资源 public void DownLoadRes () { InitUpdateList (); DownLoadMananger.GetInstance ().InitParam (); DownLoadMananger.GetInstance ().downFinish = DownLoadFinish; DownLoadMananger.GetInstance ().downLoadOneFinish = ReplaceLocalRes; DownLoadMananger.GetInstance ().downLoadProgress = downloadProgress; List<string> urlList = new List<string> (); for (int i = 0; i < localResVersion.Count; i++) { urlList.Add (SERVER_RES_URL + localResVersion [i] + "?time=" + System.DateTime.Now.Ticks); } DownLoadMananger.GetInstance ().StartDownLoad (urlList); } //下载完成回调 void DownLoadFinish () { UpdateLocalVersion (GlobalConfig.version); if (updateFinish != null) { GLogger.Log ("=====DownLoadRes==finish=====" + GlobalConfig.version); updateFinish (); } } public bool isNeedDownloadRes () { return totalUpdateResList.Count > 0; } private void ReplaceLocalRes (string fileName, WWW wwwData) { byte[] data = wwwData.bytes; string path = LOCAL_RES_PATH.Replace ("file://", ""); GLogger.Log (path + " replace"); string filePath = path + fileName; FileStream stream; if (File.Exists (filePath)) { stream = new FileStream (filePath, FileMode.Create); } else { CreateDic (filePath); stream = File.Create (filePath); } stream.Write (data, 0, data.Length); stream.Flush (); stream.Close (); } public bool isHasNewRes (string assetName) { int index = totalUpdateResList.IndexOf (assetName); // GLogger.Log (LitJson.JsonMapper.ToJson (totalUpdateResList) + " " + assetName + " " + index); return index >= 0; } //解析更新的资源,并计算更新的总大小 private void ParseVersionFile (string content, List<string> dict) { if (content == null || content.Trim ().Length == 0) { isDownloaded = true; // if (parseFinishCallBack != null) { // parseFinishCallBack (); // } return; } string appendRes = ""; string[] items = content.Split ('\n'); string[] res; isUpdateDB = false; foreach (string item in items) { if (item != null && item.Trim ().Length > 0) { res = item.Split ('#'); if (res.Length >= 2) { updateTotalSize += (float)System.Convert.ToDouble (res [1]); dict.Add (res [0]); if (res [0] == SQLiteDataInit.DBFileName) { isUpdateDB = true; } if (totalUpdateResList.IndexOf (res [0]) < 0) { totalUpdateResList.Add (res [0]); appendRes += res [0] + "\n"; } if (res.Length >= 3 && res [2] != "") { string[] resNames = res [2].Split ('|'); for (int i = 0; i < resNames.Length; i++) { totalUpdateResList.Add (resNames [i]); appendRes += resNames [i] + "\n"; } } } } } if (appendRes != "") { string path = LOCAL_RES_PATH.Replace ("file://", "") + UPDATE_RES_LIST; CreateDic (path); FileStream fs; if (!File.Exists (path)) { fs = new FileStream (path, FileMode.Create); } else { fs = new FileStream (path, FileMode.Append); } byte[] bytes = Encoding.UTF8.GetBytes (appendRes); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } // updateTotalSize = updateTotalSize; // if (parseFinishCallBack != null) { // parseFinishCallBack (); // } } //创建路径 void CreateDic (string filePath) { int index = filePath.LastIndexOf ('/'); string dir = filePath.Substring (0, index + 1); if (!Directory.Exists (dir)) { Directory.CreateDirectory (dir); } } string GetOldUpdateList () { string path = LOCAL_RES_PATH.Replace ("file://", "") + UPDATE_RES_LIST; CreateDic (path); return GetFileContent (path); } //更新本地文件的版本号 public void UpdateLocalVersion (string version) { string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; CreateDic (path); if (File.Exists (path)) { File.Delete (path); } FileStream fs = new FileStream (path, FileMode.Create); byte[] bytes = Encoding.UTF8.GetBytes (version.ToString ()); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } //更新本地文件的版本号 public void SaveDll (string version) { string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; CreateDic (path); if (File.Exists (path)) { File.Delete (path); } FileStream fs = new FileStream (path, FileMode.Create); byte[] bytes = Encoding.UTF8.GetBytes (version.ToString ()); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } //获取本地文件的版本号 public string GetLocalVersion () { //Open the stream and read it back. string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; GLogger.Log (path); string version = GetFileContent (path); if (version == "") { return GlobalConfig.version; } else { // int txtIndex = version.LastIndexOf ("."); // int txtVersion = Convert.ToInt32 (version.Substring (0, txtIndex).Replace (".", "")); // // int cfgIndex = version.LastIndexOf ("."); // int cfgVersion = Convert.ToInt32 (GlobalConfig.version.Substring (0, cfgIndex).Replace (".", "")); //改为比较整个版本号,取两个中较大的,避免version版本同时低于资源版本和GlobalConfig版本时会更新资源而不是解压资源 int txtVersion = GameUtils.ConvertVersionInt(version); int cfgVersion = GameUtils.ConvertVersionInt(GlobalConfig.version); return txtVersion >= cfgVersion ? version : GlobalConfig.version; } // return version.Replace ("\n", ""); } string GetFileContent (string path) { if (!File.Exists (path)) { return ""; } StringBuilder sb = new StringBuilder (); StreamReader sr = new StreamReader (path, Encoding.Default); string line; while ((line = sr.ReadLine ()) != null) { sb.Append (line + "\n"); } sr.Close (); return sb.ToString (); } } using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System; //using System; /// <summary> /// 1、从服务器获取版本号,和当前客户端存储的版本号进行对比, /// a、如果相同则不更新 /// b、如果不同,则从服务器获取需要更新的资源列表文件version.txt,再没有进行大版本更新的时候,这个列表是进行累加的。; /// c、文件更新后,修改客户端本地的版本号存储到version.txt文件中。 /// </summary> /// /// <summary> /// 1.在vs中新建一个代码库工程,命名为test //2.添加几个类Scirpt,Scirpt2,Data //3.将这个项目生成DLL,test.dll //4.新建一个unity项目,将DLL倒入到Asset,改名为test.bytes,不然可能会报错 //5.利用我们之前实现过的打包脚本,将test.bytes打包成test.assetbundle。 //6.创建CodeUpdate.cs脚本,用于加载代码资源,反射调用。 //7.为了验证代码更新后,可以直接加载使用,我们可以更改一下Data.cs的代码,重复以上过程,可以看到,更新了代码打包后,我们重新运行游戏,就可以看到效果 /// </summary> public class ResourceUpdateFromLocal : MonoBehaviour { private static ResourceUpdateFromLocal instance; //需要更新的资源直接是一行一个需要更新的资源,格式为:资源名#资源大小#资源名称|资源名称|资源名称 public static readonly string UPDATE_RES_LIST = "updateResList.txt"; //本地存储版本号 public static readonly string LOCAL_VERSION = "version.txt"; //需要更新的所有的dll public static readonly string Dll_VERSION_FLIE = "lxxc_dll.unity3d"; //格式为:资源名(为更新的资源名)#GameObject.name_c#clssName_GameObject.name_c#clssName public static readonly string Dll_TO_RES_VERSION_FLIE = "dynamicRes.txt"; public static string LOCAL_RES_URL = ""; public static string SERVER_RES_URL = ""; public static string LOCAL_RES_PATH = ""; public delegate void HandleFinishDownload (WWW www); private static List<string> localResVersion; private static List<string> totalUpdateResList; //格式为:资源名, GameObject.name_c#clssName_GameObject.name_c#clssName; private Dictionary<string, string> dll2Res; private System.Reflection.Assembly assembly; public DownLoadMananger.DownFinish updateFinish; public DownLoadMananger.DownLoadResProgress downloadProgress; //下载版本文件,解析成功后回调 public delegate void ParseUpdateListCallback(); public ParseUpdateListCallback parseFinishCallBack; //本次更新资源总大小 public static float updateTotalSize; //是否需要更新db public static bool isUpdateDB = false; //是否下载完成 public static bool isDownloaded = true; //当前下载的文件进度 public static float currentDownNum = 0f; private int totalNum = 1; public static WWW currentWWW ; /// <summary> /// 获取ResourceUpdate单例对象 /// </summary> /// <returns>The instance.</returns> public static ResourceUpdateFromLocal GetInstance () { return instance; } // Use this for initialization void Awake () { LOCAL_RES_PATH = GameUtils.GetDocumentsPath() + "/"; LOCAL_RES_URL = GameUtils.GetDocumentsPath () + "/"; instance = this; localResVersion = new List<string> (); GLogger.Log (Application.dataPath + "==========" + LOCAL_RES_URL); } void InitUpdateList(){ if (SERVER_RES_URL != "") { return; } ResetServerPath (); string result = GetOldUpdateList (); GLogger.Log (Application.dataPath + "=====3333=====" + result); if (result != "") { string[] items = result.Split (new char[] { '\n' }); totalUpdateResList = new List<string> (items); } else { totalUpdateResList = new List<string> (); } } void ResetServerPath(){ #if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX SERVER_RES_URL = "file://" + Application.streamingAssetsPath + "/"; #elif UNITY_WEBPLAYER SERVER_RES_URL = "StreamingAssets/"; #elif UNITY_IPHONE || UNITY_IOS || UNITY_IPHONE_API SERVER_RES_URL = "file://" + Application.dataPath + "/Raw/"; #elif UNITY_ANDROID SERVER_RES_URL = Application.streamingAssetsPath + "/"; #endif } // Update is called once per frame void Update () { } //下载更新资源 public void DownloadServerVersionTxt () { NetDataRequestTip.showLoading (); isDownloaded = false; InitUpdateList (); updateTotalSize = 0; //先下载资源更新的列表文件 DownLoadMananger.GetInstance ().InitParam (); DownLoadMananger.GetInstance ().downLoadOneFinish = DownLoadUplistFinish; DownLoadMananger.GetInstance ().downFinish = DownUpdateListFinish; List<string> list = new List<string> (); list.Add (SERVER_RES_URL + UPDATE_RES_LIST); DownLoadMananger.GetInstance ().StartDownLoad (list); } void DownLoadUplistFinish(string file, WWW wwwData){ NetDataRequestTip.removeLoading(); ParseVersionFile (wwwData.text, localResVersion); } void DownUpdateListFinish(){ if (parseFinishCallBack != null) { parseFinishCallBack (); } } public int GetTotalDownNum(){ return totalNum; } //依次加载需要更新的资源 public void DownLoadRes () { InitUpdateList (); DownLoadMananger.GetInstance ().InitParam (); DownLoadMananger.GetInstance ().downFinish = DownLoadFinish; DownLoadMananger.GetInstance ().downLoadOneFinish = ReplaceLocalRes; DownLoadMananger.GetInstance ().downLoadProgress = downloadProgress; List<string> urlList = new List<string>(); for (int i = 0; i < localResVersion.Count; i++) { urlList.Add (SERVER_RES_URL + localResVersion[i]); } DownLoadMananger.GetInstance ().StartDownLoad (urlList); } //下载完成回调 void DownLoadFinish(){ UpdateLocalVersion (GlobalConfig.version); if (updateFinish != null) { GLogger.Log ( "=====DownLoadRes==finish=====" + GlobalConfig.version); updateFinish (); } } private void ReplaceLocalRes (string fileName, WWW wwwData) { byte[] data = wwwData.bytes; string path = LOCAL_RES_PATH.Replace ("file://", ""); GLogger.Log (path + " replace"); string filePath = path + fileName; FileStream stream; if (File.Exists (filePath)) { stream = new FileStream (filePath, FileMode.Create); } else { CreateDic (filePath); stream = File.Create (filePath); } stream.Write (data, 0, data.Length); stream.Flush (); stream.Close (); } public bool isHasNewRes(string assetName){ int index = totalUpdateResList.IndexOf (assetName); // GLogger.Log (LitJson.JsonMapper.ToJson (totalUpdateResList) + " " + assetName + " " + index); return index >= 0; } //解析更新的资源,并计算更新的总大小 private void ParseVersionFile (string content, List<string> dict) { if (content == null || content.Trim().Length == 0) { isDownloaded = true; // if (parseFinishCallBack != null) { // parseFinishCallBack (); // } return; } string appendRes = ""; string[] items = content.Split ('\n'); string[] res; isUpdateDB = false; foreach (string item in items) { if (item != null && item.Trim().Length > 0) { res = item.Split ('#'); if (res.Length >= 2) { updateTotalSize += (float)System.Convert.ToDouble (res [1]); dict.Add (res[0]); if (res [0] == SQLiteDataInit.DBFileName) { isUpdateDB = true; } if (totalUpdateResList.IndexOf (res [0]) < 0) { totalUpdateResList.Add (res [0]); appendRes += res [0] + "\n"; } if (res.Length >= 3 && res [2] != "") { string[] resNames = res [2].Split ('|'); for (int i = 0; i < resNames.Length; i++) { totalUpdateResList.Add (resNames [i]); appendRes += resNames [i] + "\n"; } } } } } if (appendRes != "") { string path = LOCAL_RES_PATH.Replace ("file://", "") + UPDATE_RES_LIST; CreateDic (path); FileStream fs; if (!File.Exists (path)) { fs = new FileStream (path, FileMode.Create); } else { fs = new FileStream (path, FileMode.Append); } byte[] bytes = Encoding.UTF8.GetBytes (appendRes); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } // updateTotalSize = updateTotalSize; // if (parseFinishCallBack != null) { // parseFinishCallBack (); // } } //创建路径 void CreateDic(string filePath){ int index = filePath.LastIndexOf ('/'); string dir = filePath.Substring (0, index + 1); if (!Directory.Exists (dir)) { Directory.CreateDirectory (dir); } } string GetOldUpdateList(){ string path = LOCAL_RES_PATH.Replace ("file://", "") + UPDATE_RES_LIST; CreateDic (path); return GetFileContent(path); } public bool isNeedUnZipLocalRes(){ string dbDecompressPath = GameUtils.GetDocumentsPath().Replace("file://", "") + "/" + LOCAL_VERSION; if (File.Exists(dbDecompressPath)) { string version = GetFileContent (dbDecompressPath); if(GameUtils.ConvertVersionInt(version) >= GameUtils.ConvertVersionInt(GlobalConfig.version)) return false; } return true; } //更新本地文件的版本号 public void UpdateLocalVersion (string version) { string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; CreateDic (path); if (File.Exists (path)) { File.Delete (path); } FileStream fs = new FileStream (path, FileMode.Create); byte[] bytes = Encoding.UTF8.GetBytes (version.ToString ()); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } //更新本地文件的版本号 public void SaveDll (string version) { string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; CreateDic (path); if (File.Exists (path)) { File.Delete (path); } FileStream fs = new FileStream (path, FileMode.Create); byte[] bytes = Encoding.UTF8.GetBytes (version.ToString ()); fs.Write (bytes, 0, bytes.Length); fs.Flush (); fs.Close (); } //获取本地文件的版本号 public string GetLocalVersion () { //Open the stream and read it back. string path = LOCAL_RES_PATH.Replace ("file://", "") + LOCAL_VERSION; GLogger.Log (path); string version = GetFileContent(path); if (version == "") { return GlobalConfig.version; }else{ // int txtIndex = version.LastIndexOf ("."); // int txtVersion = Convert.ToInt32 (version.Substring (0, txtIndex).Replace (".", "")); // // int cfgIndex = version.LastIndexOf ("."); // int cfgVersion = Convert.ToInt32 (GlobalConfig.version.Substring (0, cfgIndex).Replace (".", "")); //改为比较整个版本号,取两个中较大的,避免version版本同时低于资源版本和GlobalConfig版本时会更新资源而不是解压资源 int txtVersion = GameUtils.ConvertVersionInt(version); int cfgVersion = GameUtils.ConvertVersionInt(GlobalConfig.version); return txtVersion >= cfgVersion ? version : GlobalConfig.version; } // return version.Replace("\n", ""); } string GetFileContent(string path){ if (!File.Exists (path)) { return ""; } StringBuilder sb = new StringBuilder (); StreamReader sr = new StreamReader(path,Encoding.Default); string line; while ((line = sr.ReadLine()) != null) { sb.Append(line + "\n"); } sr.Close (); return sb.ToString (); } } using UnityEngine; using System.Collections; using System.Collections.Generic; public class DownLoadMananger : MonoBehaviour { private static DownLoadMananger instance; public delegate void HandleFinishDownload (WWW www); private List<string> localResVersion; private WWW currentWWW ; //下载完成事件 public delegate void DownFinish(); public DownFinish downFinish; //下载过程事件 public delegate void DownLoadResProgress(float progress); public DownLoadResProgress downLoadProgress; //下载过程事件 public delegate void DownLoadOneFinish(string fileName, WWW wwwData); public DownLoadOneFinish downLoadOneFinish; //当前正在下载的文件 private int currentDownNum = 0; private float totalNum = 0; //下载的所有文件的总进度 private float totalProgress = 0.0f; public static DownLoadMananger GetInstance () { return instance; } // Use this for initialization void Awake () { instance = this; } // Update is called once per frame void Update () { if (currentWWW != null) { totalProgress = (currentDownNum + currentWWW.progress) / totalNum; if (downLoadProgress != null) { downLoadProgress (totalProgress); } // GLogger.Log (downLoadProgress + "=====DownLoadRes=======" + totalProgress + " " + totalNum); } } public void InitParam(){ downFinish = null; downLoadProgress = null; downLoadOneFinish = null; currentDownNum = 0; totalNum = 0; totalProgress = 0f; } //依次加载需要更新的资源 public void StartDownLoad (List<string> resList) { //如果下载列表为null,直接回调结束 if (resList == null || resList.Count <= 0) { FinishCallback (); return; } localResVersion = resList; totalNum = (float)localResVersion.Count; DownLoadFile (); } void FinishCallback(){ if (downFinish != null) { downFinish (); } } void DownLoadFile(){ if (localResVersion == null || (localResVersion != null && localResVersion.Count <= 0)) { FinishCallback (); return; } string file = localResVersion [0]; if (file == null || file.Trim ().Length == 0) { localResVersion.RemoveAt (0); currentDownNum++; currentWWW = null; DownLoadFile(); return; } GLogger.LogWarning("__________"+localResVersion[0]); StartCoroutine (this.DownLoad (file, delegate(WWW w) { GLogger.LogWarning("__________"+localResVersion[0]); //将下载的资源替换本地就的资源 if(downLoadOneFinish != null){ int end = file.Length - (file.LastIndexOf('/') + 1); int index = file.IndexOf("?"); if(index >= 0){ end = index - 1 - file.LastIndexOf('/'); } // GLogger.LogError(file + " " + end); downLoadOneFinish(file.Substring((file.LastIndexOf('/') + 1),end), w); } localResVersion.RemoveAt (0); currentDownNum++; if(localResVersion.Count > 0){ } currentWWW = null; DownLoadFile (); })); } //下载文件 private IEnumerator DownLoad (string url, HandleFinishDownload finishFun) { WWW www = new WWW (url); GLogger.Log (url + "----------"); currentWWW =www; yield return www; bool hasError = false; if (www.error != null) { hasError = true; } if (www.isDone) { if (www.bytesDownloaded > 0 && !hasError) { if (finishFun != null) { GLogger.LogWarning (url + "---------------------------"); finishFun (www); } } else { GLogger.Log (url + " ***load error **www.bytesDownloaded is *****" + www.bytesDownloaded + " error is" + www.error.ToString() ); currentWWW = null; www.Dispose (); NetDataRequestTip.removeLoading (); AlertConfirmController.GetInstance ().pushAlertMsg (CNString.DOWN_RES_ERROR, delegate(bool isConfirm){ if(isConfirm){ GLogger.LogWarning(url); StartCoroutine(DownLoad(url, finishFun)); } else{ #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else Application.Quit (); #endif } }); } } else { currentWWW = null; } www.Dispose (); www = null; System.GC.Collect (); } } |