当前位置:   article > 正文

Unity 基础 之 使用 WWW / UnityWebRequest / UnityWebRequestAssetBundle 加载 AssetBundle (AB包)的方法简单使用

unitywebrequestassetbundle

Unity 基础 之 使用 WWW / UnityWebRequest / UnityWebRequestAssetBundle 加载 AssetBundle (AB包)的方法简单使用

 

目录

Unity 基础 之 使用 WWW / UnityWebRequest / UnityWebRequestAssetBundle 加载 AssetBundle (AB包)的方法简单使用

一、简单介绍

二、实现原理

三、效果预览

四、简单实现步骤

五、关键代码


 

一、简单介绍

Unity中的一些基础知识点。

本节介绍,在Unity 应用的时候,加载 AB 包的方式,WWW (老方法),UnityWebRequest (新方法,建议使用该方法)加载 AB 包的方式使用,方便以后进行热更新资源包使用。

 

二、实现原理

1、WWW _www = new WWW(uriPath);

AssetBundle ab = _www.assetBundle;

2、UnityWebRequest request = UnityWebRequest.Get(uriPath);

byte[] results = request.downloadHandler.data;
AssetBundle ab = AssetBundle.LoadFromMemory(results);

3、UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath);

AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

 

三、效果预览

 

四、简单实现步骤

1、新建一个空工程

 

2、把资源打包成 ab 包 (BuildAB 脚本代码,贴在后面)

 

3、编写加载AB资源脚本 WWWAndUnitywebRequestLoadAB

 

4、把脚本挂载到场景中,并把场景中的 New Sprite 赋值脚本,用户来测试 AB 包中的图片

 

5、根据需要测试代码,运行场景,效果如上

 

五、关键代码

1、WWWAndUnitywebRequestLoadAB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Networking;
  6. public class WWWAndUnitywebRequestLoadAB : MonoBehaviour
  7. {
  8. public SpriteRenderer sr;
  9. string dirPath = Application.streamingAssetsPath + "/AB/tests/tests.ab";
  10. private void Start()
  11. {
  12. //StartCoroutine(WWWLoadAB(dirPath, (ab) => {
  13. // //实例化
  14. // GameObject obj = ab.LoadAsset<GameObject>("Cube");
  15. // Instantiate(obj);
  16. // Sprite sp = ab.LoadAsset<Sprite>("bird");
  17. // sr.sprite = sp;
  18. //}));
  19. //StartCoroutine(UnityWebRequestLoadAB1(dirPath, (ab) =>
  20. //{
  21. // //实例化
  22. // GameObject obj = ab.LoadAsset<GameObject>("Cube");
  23. // Instantiate(obj);
  24. // Sprite sp = ab.LoadAsset<Sprite>("bird");
  25. // sr.sprite = sp;
  26. //}));
  27. StartCoroutine(UnityWebRequestLoadAB2(dirPath, (ab) =>
  28. {
  29. //实例化
  30. GameObject obj = ab.LoadAsset<GameObject>("Cube");
  31. Instantiate(obj);
  32. Sprite sp = ab.LoadAsset<Sprite>("bird");
  33. sr.sprite = sp;
  34. }));
  35. }
  36. IEnumerator WWWLoadAB(string uriPath, Action<AssetBundle> loadABFinishedAction) {
  37. WWW _www = new WWW(uriPath);
  38. yield return _www;
  39. //检查是否发生错误
  40. if (string.IsNullOrEmpty(_www.error))
  41. {
  42. //检查AssetBundle是否为空
  43. if (_www.assetBundle != null)
  44. {
  45. AssetBundle ab = _www.assetBundle;
  46. if (loadABFinishedAction != null)
  47. {
  48. loadABFinishedAction(ab);
  49. }
  50. }
  51. }
  52. else
  53. {
  54. Debug.Log("_www.error: " + _www.error);
  55. }
  56. }
  57. IEnumerator UnityWebRequestLoadAB1(string uriPath, Action<AssetBundle> loadABFinishedAction)
  58. {
  59. UnityWebRequest request = UnityWebRequest.Get(uriPath);
  60. yield return request.SendWebRequest();
  61. if (request.isHttpError)
  62. {
  63. Debug.LogError(GetType() + "/ERROR/" + request.error);
  64. }
  65. else {
  66. byte[] results = request.downloadHandler.data;
  67. AssetBundle ab = AssetBundle.LoadFromMemory(results);
  68. if (loadABFinishedAction != null)
  69. {
  70. loadABFinishedAction(ab);
  71. }
  72. }
  73. }
  74. IEnumerator UnityWebRequestLoadAB2(string uriPath, Action<AssetBundle> loadABFinishedAction)
  75. {
  76. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath);
  77. yield return request.SendWebRequest();
  78. if (request.isHttpError)
  79. {
  80. Debug.LogError(GetType() + "/ERROR/" + request.error);
  81. }
  82. else
  83. {
  84. AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
  85. if (loadABFinishedAction != null)
  86. {
  87. loadABFinishedAction(ab);
  88. }
  89. }
  90. }
  91. }

 

2、BuildAB(仅供参考资源 ab 打包使用)

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using UnityEditor;
  5. using UnityEngine;
  6. public class BuildAB : Editor
  7. {
  8. static string dirPath = Application.streamingAssetsPath + "/AB";
  9. [MenuItem("ABTools/BuildAB ---- 把资源打包AB包资源")]
  10. static void ABXmlZipToStreamingAssetsPath()
  11. {
  12. RemoveABLabel();
  13. SetABLabel();
  14. ABBuilder();
  15. RemoveABLabel();
  16. //Directory.Delete(dirPath, true);
  17. AssetDatabase.Refresh();
  18. }
  19. static void ABBuilder()
  20. {
  21. if (Directory.Exists(dirPath) == false)
  22. {
  23. Directory.CreateDirectory(dirPath);
  24. }
  25. // BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath + "/AB", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
  26. BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath + "/AB", BuildAssetBundleOptions.None, BuildTarget.Android);
  27. // AssetDatabase.Refresh();
  28. }
  29. #region RemoveABLabel
  30. public static void RemoveABLabel()
  31. {
  32. // 需要移除标记的根目录
  33. string strNeedRemoveLabelRoot = string.Empty;
  34. // 目录信息(场景目录信息数组,表示所有根目录下场景目录)
  35. DirectoryInfo[] directoryDIRArray = null;
  36. // 定义需要移除AB标签的资源的文件夹根目录
  37. //strNeedRemoveLabelRoot = PathTools.GetABResourcesPath();
  38. strNeedRemoveLabelRoot = Application.dataPath + "/Resources";
  39. //Debug.Log("strNeedSetLabelRoot = "+strNeedSetLabelRoot);
  40. DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedRemoveLabelRoot);
  41. directoryDIRArray = dirTempInfo.GetDirectories();
  42. // 遍历本场景目录下所有的目录或者文件
  43. foreach (DirectoryInfo currentDir in directoryDIRArray)
  44. {
  45. // 递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
  46. JudgeDirOrFileByRecursive(currentDir);
  47. }
  48. // 清空无用的 AB 标记
  49. AssetDatabase.RemoveUnusedAssetBundleNames();
  50. // 刷新
  51. AssetDatabase.Refresh();
  52. // 提示信息,标记包名完成
  53. Debug.Log("AssetBundle 本次操作移除标记完成");
  54. }
  55. /// <summary>
  56. /// 递归判断判断是否是目录或文件
  57. /// 是文件,修改 Asset Bundle 标记
  58. /// 是目录,则继续递归
  59. /// </summary>
  60. /// <param name="fileSystemInfo">当前文件信息(文件信息与目录信息可以相互转换)</param>
  61. private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo)
  62. {
  63. // 调试信息
  64. //Debug.Log("currentDir.Name = " + fileSystemInfo.Name);
  65. //Debug.Log("sceneName = " + sceneName);
  66. // 参数检查
  67. if (fileSystemInfo.Exists == false)
  68. {
  69. Debug.LogError("文件或者目录名称:" + fileSystemInfo + " 不存在,请检查");
  70. return;
  71. }
  72. // 得到当前目录下一级的文件信息集合
  73. DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; // 文件信息转为目录信息
  74. FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos();
  75. foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
  76. {
  77. FileInfo fileInfoObj = fileInfo as FileInfo;
  78. // 文件类型
  79. if (fileInfoObj != null)
  80. {
  81. // 修改此文件的 AssetBundle 标签
  82. RemoveFileABLabel(fileInfoObj);
  83. }
  84. // 目录类型
  85. else
  86. {
  87. // 如果是目录,则递归调用
  88. JudgeDirOrFileByRecursive(fileInfo);
  89. }
  90. }
  91. }
  92. /// <summary>
  93. /// 给文件移除 Asset Bundle 标记
  94. /// </summary>
  95. /// <param name="fileInfoObj">文件(文件信息)</param>
  96. static void RemoveFileABLabel(FileInfo fileInfoObj)
  97. {
  98. // 调试信息
  99. //Debug.Log("fileInfoObj.Name = " + fileInfoObj.Name);
  100. //Debug.Log("scenesName = " + scenesName);
  101. // 参数定义
  102. // AssetBundle 包名称
  103. string strABName = string.Empty;
  104. // 文件路径(相对路径)
  105. string strAssetFilePath = string.Empty;
  106. // 参数检查(*.meta 文件不做处理)
  107. if (fileInfoObj.Extension == ".meta")
  108. {
  109. return;
  110. }
  111. // 得到 AB 包名称
  112. strABName = string.Empty;
  113. // 获取资源文件的相对路径
  114. int tmpIndex = fileInfoObj.FullName.IndexOf("Assets");
  115. strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex); // 得到文件相对路径
  116. // 给资源文件移除 AB 名称
  117. AssetImporter tmpImportObj = AssetImporter.GetAtPath(strAssetFilePath);
  118. tmpImportObj.assetBundleName = strABName;
  119. }
  120. #endregion
  121. #region SetABLabel
  122. public static void SetABLabel()
  123. {
  124. // 需要做标记的根目录
  125. string strNeedSetLabelRoot = string.Empty;
  126. // 目录信息(场景目录信息数组,表示所有根目录下场景目录)
  127. DirectoryInfo[] directoryDIRArray = null;
  128. // 清空无用的 AB 标记
  129. AssetDatabase.RemoveUnusedAssetBundleNames();
  130. // 定义需要打包资源的文件夹根目录
  131. //strNeedSetLabelRoot = PathTools.GetABResourcesPath();
  132. strNeedSetLabelRoot = Application.dataPath + "/Resources/XAN/AB";
  133. //Debug.Log("strNeedSetLabelRoot = "+strNeedSetLabelRoot);
  134. DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedSetLabelRoot);
  135. directoryDIRArray = dirTempInfo.GetDirectories();
  136. //2、 遍历本场景目录下所有的目录或者文件
  137. foreach (DirectoryInfo currentDir in directoryDIRArray)
  138. {
  139. //2.1:遍历本场景目录下所有的目录或者文件
  140. // 如果是目录,则继续“递归”访问里面的文件,直到定位到文件
  141. string tmpScenesDir = strNeedSetLabelRoot + "/" + currentDir.Name; // Unity /xx/xx 全路径
  142. //DirectoryInfo tmpScenesDirInfo = new DirectoryInfo(tmpScenesDir);
  143. int tmpIndex = tmpScenesDir.LastIndexOf("/");
  144. string tmpScenesName = tmpScenesDir.Substring(tmpIndex + 1); // 场景名称
  145. //Debug.Log("tmpScenesDir = "+ tmpScenesDir);
  146. //2、2 递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
  147. JudgeDirOrFileByRecursive(currentDir, tmpScenesName);
  148. }
  149. // 刷新
  150. AssetDatabase.Refresh();
  151. // 提示信息,标记包名完成
  152. Debug.Log("AssetBundle 本次操作设置标记完成");
  153. }
  154. /// <summary>
  155. /// 递归判断判断是否是目录或文件
  156. /// 是文件,修改 Asset Bundle 标记
  157. /// 是目录,则继续递归
  158. /// </summary>
  159. /// <param name="fileSystemInfo">当前文件信息(文件信息与目录信息可以相互转换)</param>
  160. /// <param name="sceneName">当前场景名称</param>
  161. private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo, string sceneName)
  162. {
  163. // 调试信息
  164. //Debug.Log("currentDir.Name = " + fileSystemInfo.Name);
  165. //Debug.Log("sceneName = " + sceneName);
  166. // 参数检查
  167. if (fileSystemInfo.Exists == false)
  168. {
  169. Debug.LogError("文件或者目录名称:" + fileSystemInfo + " 不存在,请检查");
  170. return;
  171. }
  172. // 得到当前目录下一级的文件信息集合
  173. DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; // 文件信息转为目录信息
  174. FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos();
  175. foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
  176. {
  177. FileInfo fileInfoObj = fileInfo as FileInfo;
  178. // 文件类型
  179. if (fileInfoObj != null)
  180. {
  181. // 修改此文件的 AssetBundle 标签
  182. SetFileABLabel(fileInfoObj, sceneName);
  183. }
  184. // 目录类型
  185. else
  186. {
  187. // 如果是目录,则递归调用
  188. JudgeDirOrFileByRecursive(fileInfo, sceneName);
  189. }
  190. }
  191. }
  192. /// <summary>
  193. /// 给文件打 Asset Bundle 标记
  194. /// </summary>
  195. /// <param name="fileInfoObj">文件(文件信息)</param>
  196. /// <param name="scenesName">场景名称</param>
  197. static void SetFileABLabel(FileInfo fileInfoObj, string scenesName)
  198. {
  199. // 调试信息
  200. //Debug.Log("fileInfoObj.Name = " + fileInfoObj.Name);
  201. //Debug.Log("scenesName = " + scenesName);
  202. // 参数定义
  203. // AssetBundle 包名称
  204. string strABName = string.Empty;
  205. // 文件路径(相对路径)
  206. string strAssetFilePath = string.Empty;
  207. // 参数检查(*.meta 文件不做处理)
  208. if (fileInfoObj.Extension == ".meta")
  209. {
  210. return;
  211. }
  212. // 得到 AB 包名称
  213. strABName = GetABName(fileInfoObj, scenesName);
  214. // 获取资源文件的相对路径
  215. int tmpIndex = fileInfoObj.FullName.IndexOf("Assets");
  216. strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex); // 得到文件相对路径
  217. // 给资源文件设置AB名称以及后缀
  218. AssetImporter tmpImportObj = AssetImporter.GetAtPath(strAssetFilePath);
  219. tmpImportObj.assetBundleName = strABName;
  220. // 判断文件是否是场景文件
  221. if (fileInfoObj.Extension == ".unity")
  222. {
  223. // 定义AB包的场景扩展名
  224. tmpImportObj.assetBundleVariant = "u3d";
  225. }
  226. else
  227. {
  228. // 定义AB包的非场景扩展名
  229. tmpImportObj.assetBundleVariant = "ab";
  230. }
  231. }
  232. /// <summary>
  233. /// 获取 AB 包的名称
  234. /// </summary>
  235. /// <param name="fileInfoObj">文件信息</param>
  236. /// <param name="scenesName">场景名称</param>
  237. /// AB 包名形成规则:
  238. /// 文件AB包名称 = “所在二级目录名称”(场景名称)+“三级目录名称”(类型名称)
  239. /// <returns></returns>
  240. static string GetABName(FileInfo fileInfoObj, string scenesName)
  241. {
  242. // 返回AB包名称
  243. string strABName = string.Empty;
  244. // win 路径
  245. string tmpWinPath = fileInfoObj.FullName;
  246. // 转为 Unity 路径格式
  247. string tmpUnityPath = tmpWinPath.Replace("\\", "/");
  248. // 定位“场景名称”后面字符位置
  249. int tmpSceneNamePosition = tmpUnityPath.IndexOf(scenesName) + scenesName.Length;
  250. // AB 包中 “类型名称”所在区域
  251. string strABFileNameArea = tmpUnityPath.Substring(tmpSceneNamePosition + 1);
  252. //测试
  253. //Debug.Log(" strABFileNameArea = " + strABFileNameArea);
  254. // 非场景资源
  255. if (strABFileNameArea.Contains("/"))
  256. {
  257. string[] tmpStrArray = strABFileNameArea.Split('/');
  258. //测试
  259. //Debug.Log("tmpStrArray[0] = "+ tmpStrArray[0]);
  260. // AB 包名称正式形成
  261. strABName = scenesName + "/" + tmpStrArray[0];
  262. }
  263. // 场景资源
  264. else
  265. {
  266. // 定义*.unity 文件形成的特殊 AB 包名称
  267. strABName = scenesName + "/" + scenesName;
  268. }
  269. return strABName;
  270. }
  271. #endregion
  272. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/95772
推荐阅读
相关标签
  

闽ICP备14008679号