热更新

Editor目录下CreateAssetBundle.cs

  1. /*
  2. * created by shenjun
  3. */
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using UnityEditor;
  8. using UnityEngine.Networking;
  9. namespace shenjun
  10. {
  11. public class CreateAssetBundle : EditorWindow
  12. {
  13. public static string createAssetPath{ get { return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Build/"; }}
  14. static CreateAssetBundle window;
  15. int platformSelect = 0;
  16. string[] platformName = { "Windows", "Mac OS", "IOS", "Android", "All" };
  17. string assetbundlePath = "";
  18. string Path
  19. {
  20. set {
  21. assetbundlePath = value;
  22. }
  23. get
  24. {
  25. if(string.IsNullOrEmpty(assetbundlePath))
  26. {
  27. assetbundlePath = createAssetPath;
  28. }
  29. return assetbundlePath;
  30. }
  31. }
  32. [MenuItem("AssetBundle/CreateAssetBundleTools")]
  33. static void ShowWindow()
  34. {
  35. if (window == null)
  36. {
  37. window = EditorWindow.GetWindow<CreateAssetBundle>(true, "AssetBundle Tools");
  38. window.minSize = new Vector2(800, 600);
  39. }
  40. window.Show();
  41. }
  42. void OnGUI()
  43. {
  44. platformSelect = GUILayout.SelectionGrid(platformSelect, platformName, platformName.Length);
  45. GUILayout.BeginHorizontal();
  46. GUILayout.Label("打包路径:");
  47. GUILayout.Label(Path);
  48. if(GUILayout.Button("选择路径", GUILayout.MaxWidth(100)))
  49. {
  50. Path = EditorUtility.OpenFolderPanel("选择文件夹", Application.dataPath, Path);
  51. }
  52. GUILayout.EndHorizontal();
  53. if (GUILayout.Button("打包"))
  54. {
  55. CreateBundle(platformSelect);
  56. EditorUtility.DisplayDialog("资源打包信息提示", "打包完成", "确定");
  57. }
  58. }
  59. void CreateBundle(int plat)
  60. {
  61. string combinePath = "";
  62. BuildTarget target = BuildTarget.NoTarget;
  63. switch(plat)
  64. {
  65. case 0:
  66. combinePath = Path + "Windows";
  67. target = BuildTarget.StandaloneWindows;
  68. break;
  69. case 1:
  70. combinePath = Path + "Mac OS";
  71. target = BuildTarget.StandaloneOSX;
  72. break;
  73. case 2:
  74. combinePath = Path + "IOS";
  75. target = BuildTarget.iOS;
  76. break;
  77. case 3:
  78. combinePath = Path + "Android";
  79. target = BuildTarget.Android;
  80. break;
  81. case 4:
  82. for (int i = 0; i < 4; i++)
  83. {
  84. CreateBundle(i);
  85. }
  86. return;
  87. }
  88. if (!System.IO.Directory.Exists(combinePath))
  89. {
  90. System.IO.Directory.CreateDirectory(combinePath);
  91. }
  92. CreateBundle(combinePath, target);
  93. }
  94. void CreateBundle(string path ,BuildTarget target)
  95. {
  96. BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.ForceRebuildAssetBundle, target);
  97. AssetDatabase.Refresh();
  98. }
  99. [MenuItem("AssetBundle/资源清理(删除本地及远程数据)")]
  100. public static void ClearDirectory()
  101. {
  102. string[] clearPath = { LoadHotUpdate.localAssetPath, LoadHotUpdate.remoteAssetPath };
  103. for (int i = 0; i < clearPath.Length; i++)
  104. {
  105. string[] fileNames = System.IO.Directory.GetFiles(clearPath[i]);
  106. for (int j = 0; j < fileNames.Length; j++)
  107. {
  108. System.IO.File.Delete(fileNames[j]);
  109. }
  110. }
  111. AssetDatabase.Refresh();
  112. }
  113. }
  114. }

HotUpdateLua.cs

  1. /*
  2. * created by shenjun
  3. */
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using System;
  8. using UnityEngine.EventSystems;
  9. using XLua;
  10. namespace shenjun
  11. {
  12. public class HotUpdateLua : MonoBehaviour, IPointerDownHandler {
  13. [CSharpCallLua]
  14. public delegate void AwakeSet(HotUpdateLua self);
  15. [CSharpCallLua]
  16. public delegate void OnPanelClick(PointerEventData eventData);
  17. LuaEnv luaEnv = new LuaEnv();
  18. AwakeSet awake;
  19. Action start;
  20. Action update;
  21. Action destroy;
  22. OnPanelClick panelClick;
  23. void Awake()
  24. {
  25. AssetBundle bundle = AssetBundle.LoadFromFile(LoadHotUpdate.localAssetPath + "luahotupdate_lua.ab");
  26. TextAsset luaAsset = bundle.LoadAsset<TextAsset>("LuaHotUpdate.lua.txt");
  27. luaEnv.DoString(luaAsset.text);
  28. awake = luaEnv.Global.Get<AwakeSet>("Awake");
  29. start = luaEnv.Global.Get<Action>("Start");
  30. update = luaEnv.Global.Get<Action>("Update");
  31. destroy = luaEnv.Global.Get<Action>("OnDestroy");
  32. panelClick = luaEnv.Global.Get<OnPanelClick>("OnPanelClick");
  33. if (awake != null) awake(this);
  34. }
  35. void Start () {
  36. if (start != null) start();
  37. }
  38. void Update () {
  39. if (update != null) update();
  40. }
  41. void OnDestroy()
  42. {
  43. awake = null;
  44. start = null;
  45. update = null;
  46. if (destroy != null)
  47. {
  48. destroy();
  49. destroy = null;
  50. }
  51. panelClick = null;
  52. luaEnv.Dispose();
  53. }
  54. public void OnPointerDown(PointerEventData eventData)
  55. {
  56. if (panelClick != null) panelClick(eventData);
  57. }
  58. }
  59. }

LoadHotUpdate.cs

  1. /*
  2. * created by shenjun
  3. */
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using System;
  8. using System.IO;
  9. using UnityEngine.Networking;
  10. using UnityEngine.UI;
  11. namespace shenjun
  12. {
  13. public class LoadHotUpdate : MonoBehaviour
  14. {
  15. static Dictionary<string, AssetBundle> bundleCaches = new Dictionary<string, AssetBundle>();
  16. static AssetBundleManifest manifest = null;
  17. public static string localAssetPath
  18. {
  19. get
  20. {
  21. // FIXME : 移动平台的路径不一样
  22. // 移动平台的话 请使用路径(具有可读写权限): Application.persistentDataPath
  23. return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Local/";
  24. //#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
  25. //#elif UNITY_IOS
  26. //#elif UNITY_ANDROID
  27. //#endif
  28. }
  29. }
  30. public static string remoteAssetPath
  31. {
  32. get
  33. {
  34. // FIXME : 移动平台的路径不一样 同 localAssetPath
  35. return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Remote/";
  36. }
  37. }
  38. void Start()
  39. {
  40. // 从服务器 下载配置文件列表 配置文件格式:txt json xml cvs
  41. // 和本地配置文件对比 版本号、资源校验码等 不同的则更新
  42. // 更新
  43. // 运行程序
  44. StartCoroutine(LoadRemoteProfile(LoadAsset));
  45. }
  46. void Update()
  47. {
  48. }
  49. private void OnDestroy()
  50. {
  51. bundleCaches.Clear();
  52. AssetBundle.UnloadAllAssetBundles(true);
  53. }
  54. IEnumerator LoadRemoteProfile(Action<string> onFinished)
  55. {
  56. //Caching.ClearCache();
  57. //while (!Caching.ready)
  58. //yield return null;
  59. string url =
  60. #if UNITY_STANDALONE_WIN
  61. "file:///" +
  62. #elif UNITY_STANDALONE_OSX
  63. "file://" +
  64. #endif
  65. remoteAssetPath + "luahotupdate_profile.ab";
  66. AssetBundle bundle = null;
  67. // 1、WWW.LoadFromCacheOrDownload 加载
  68. //using(WWW www = WWW.LoadFromCacheOrDownload(url, 0))
  69. //{
  70. // yield return www;
  71. // if (!string.IsNullOrEmpty(www.error))
  72. // {
  73. // Debug.Log(www.error);
  74. // yield break;
  75. // }
  76. // bundle = www.assetBundle;
  77. //}
  78. // 2、UnityWebRequest.GetAssetBundle 加载
  79. UnityWebRequest webRequest = UnityWebRequest.GetAssetBundle(url);
  80. yield return webRequest.SendWebRequest();
  81. if (!string.IsNullOrEmpty(webRequest.error))
  82. {
  83. Debug.Log(webRequest.error);
  84. yield break;
  85. }
  86. bundle = DownloadHandlerAssetBundle.GetContent(webRequest);
  87. // 3、AssetBundle.LoadFromFile 加载
  88. //bundle = AssetBundle.LoadFromFile(remoteAssetPath + "luahotupdate_profile.ab");
  89. // 4、AssetBundle.LoadFromFileAsync 加载
  90. //AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(remoteAssetPath + "luahotupdate_profile.ab"));
  91. //yield return request;
  92. //bundle = request.assetBundle;
  93. TextAsset profile = bundle.LoadAsset<TextAsset>("file");
  94. onFinished(profile.text);
  95. }
  96. void LoadAsset(string remoteVersion)
  97. {
  98. AssetBundle.UnloadAllAssetBundles(true);
  99. // 加载本地配置文件
  100. string profilePath = localAssetPath + "luahotupdate_profile.ab";
  101. if (!File.Exists(profilePath))
  102. {
  103. // 加载服务器文件列表
  104. LoadRemoteAsset();
  105. }
  106. else
  107. {
  108. // 加载本地列表并比较
  109. AssetBundle bundle = AssetBundle.LoadFromFile(profilePath);
  110. TextAsset profile = bundle.LoadAsset<TextAsset>("file");
  111. float localVersion, removeVersion;
  112. if (float.TryParse(profile.text, out localVersion) && float.TryParse(remoteVersion, out removeVersion))
  113. {
  114. if (removeVersion > localVersion)
  115. {
  116. // 加载服务器文件列表
  117. LoadRemoteAsset();
  118. }
  119. }
  120. }
  121. LoadPanel();
  122. }
  123. // 加载服务器文件列表
  124. void LoadRemoteAsset()
  125. {
  126. if (Directory.Exists(localAssetPath))
  127. {
  128. string[] oldFiles = Directory.GetFiles(localAssetPath);
  129. for (int i = 0; i < oldFiles.Length; i++)
  130. {
  131. File.Delete(oldFiles[i]);
  132. }
  133. Directory.Delete(localAssetPath);
  134. Directory.CreateDirectory(localAssetPath);
  135. }
  136. string[] files = Directory.GetFiles(remoteAssetPath);
  137. for (int i = 0; i < files.Length; i++)
  138. {
  139. string fileName = files[i].Substring(files[i].LastIndexOf("/", StringComparison.Ordinal) + 1);
  140. File.Copy(remoteAssetPath + fileName, localAssetPath + fileName);
  141. }
  142. }
  143. // 加载UI
  144. void LoadPanel()
  145. {
  146. LoadAssetBundleInstance("luahotupdate_ui.ab", "Panel", transform);
  147. }
  148. public static GameObject LoadAssetBundleInstance(string bundleName, string objName, Transform parent = null)
  149. {
  150. AssetBundle bundle = LoadAssetBundle(bundleName);
  151. GameObject obj = bundle.LoadAsset<GameObject>(objName);
  152. return Instantiate(obj, parent);
  153. }
  154. // 加载AssetBundle包以及依赖文件
  155. public static AssetBundle LoadAssetBundle(string bundleName)
  156. {
  157. if (manifest == null)
  158. {
  159. string platStr = "";
  160. #if UNITY_STANDALONE_WIN
  161. platStr = "Windows";
  162. #elif UNITY_STANDALONE_OSX
  163. platStr = "Mac OS";
  164. #elif UNITY_IOS
  165. platStr = "IOS";
  166. #elif UNITY_ANDROID
  167. platStr = "Android";
  168. #endif
  169. AssetBundle platBundle = AssetBundle.LoadFromFile(localAssetPath + platStr);
  170. manifest = platBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  171. }
  172. if (bundleCaches.ContainsKey(bundleName))
  173. {
  174. return bundleCaches[bundleName];
  175. }
  176. else
  177. {
  178. AssetBundle bundle = AssetBundle.LoadFromFile(localAssetPath + bundleName);
  179. bundleCaches[bundleName] = bundle;
  180. // 注意:GetAllDependencies会返回直接和间接关联的AssetBundle
  181. string[] depends = manifest.GetAllDependencies(bundleName);
  182. for (int i = 0; i < depends.Length; i++)
  183. {
  184. if (!bundleCaches.ContainsKey(depends[i]))
  185. {
  186. AssetBundle depAB = AssetBundle.LoadFromFile(localAssetPath + depends[i]);
  187. bundleCaches[depends[i]] = depAB;
  188. }
  189. }
  190. return bundle;
  191. }
  192. }
  193. }
  194. }

?