ResMgr.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { Asset, AssetManager, assetManager } from "cc";
  2. import { bundleMgr } from "./BundleMgr";
  3. /**
  4. * 资源管理器
  5. * 提供资源加载、释放功能。
  6. */
  7. class ResMgr {
  8. /** 私有构造函数 */
  9. private constructor() { }
  10. /** 单例实例 */
  11. public static readonly instance: ResMgr = new ResMgr();
  12. /**
  13. * 加载资源
  14. * @param resPath 资源路径
  15. * @param onProgress 进度回调函数
  16. * @param onComplete 完成回调函数
  17. * @returns Promise<T> 加载完成后的Promise
  18. */
  19. public async loadRes<T extends Asset>(
  20. resPath: string,
  21. onProgress?: (completedCount: number, totalCount: number, item: any) => void,
  22. onComplete?: (err: Error | null, asset: T) => void
  23. ): Promise<T> {
  24. try {
  25. const { bundleName, path } = this.path(resPath);
  26. const bundle = await bundleMgr.getBundle(bundleName);
  27. return await this.loadAsset<T>(bundle, path, onProgress, onComplete);
  28. } catch (error) {
  29. console.error(`加载资源失败: ${resPath}`, error.message);
  30. throw error;
  31. }
  32. }
  33. /**
  34. * 加载目录下的所有资源
  35. * @param resPath 资源路径
  36. * @param onProgress 进度回调函数
  37. * @param onComplete 完成回调函数
  38. * @returns Promise<Array<Asset>> 加载完成后的Promise
  39. */
  40. public async loadResDir(
  41. resPath: string,
  42. onProgress?: (completedCount: number, totalCount: number, item: any) => void,
  43. onComplete?: (err: Error | null, assets: Array<Asset>) => void
  44. ): Promise<Array<Asset>> {
  45. try {
  46. const { bundleName, path } = this.path(resPath);
  47. const bundle = await bundleMgr.getBundle(bundleName);
  48. return await this.loadAssetDir(bundle, path, onProgress, onComplete);
  49. } catch (error) {
  50. console.error(`加载目录失败: ${resPath}`, error.message);
  51. throw error;
  52. }
  53. }
  54. /**
  55. * 释放指定分包单个资源
  56. * @param resPath 资源路径
  57. */
  58. public releaseRes(resPath: string): void {
  59. const { bundleName, path } = this.path(resPath);
  60. const bundle = assetManager.getBundle(bundleName);
  61. if (bundle) {
  62. bundle.release(path);
  63. } else {
  64. console.error(`分包 ${bundleName} 未找到,无法释放资源 ${path}。`);
  65. }
  66. }
  67. /**
  68. * 释放指定分包全部资源
  69. * @param bundleName 分包名称
  70. */
  71. public releaseBundle(bundleName: string): void {
  72. const bundle = assetManager.getBundle(bundleName);
  73. if (bundle) {
  74. bundle.releaseAll();
  75. assetManager.removeBundle(bundle);
  76. } else {
  77. console.error(`分包 ${bundleName} 未找到,无法移除。`);
  78. }
  79. }
  80. /** 移除所有分包 */
  81. public releaseAll(): void {
  82. assetManager.releaseAll();
  83. }
  84. /**
  85. * 加载单个资源的辅助方法
  86. * @param bundle 资源所在的分包
  87. * @param path 资源路径
  88. * @param onProgress 进度回调函数
  89. * @param onComplete 完成回调函数
  90. * @returns Promise<T> 加载完成后的Promise
  91. */
  92. private loadAsset<T extends Asset>(
  93. bundle: AssetManager.Bundle,
  94. path: string,
  95. onProgress?: (completedCount: number, totalCount: number, item: any) => void,
  96. onComplete?: (err: Error | null, asset: T) => void
  97. ): Promise<T> {
  98. return new Promise<T>((resolve, reject) => {
  99. bundle.load(
  100. path,
  101. (completedCount, totalCount, item) => onProgress?.(completedCount, totalCount, item),
  102. (err, asset) => {
  103. onComplete?.(err, asset as T);
  104. if (err) {
  105. console.error(`从分包加载资源 ${path} 失败`, err.message);
  106. reject(err);
  107. } else {
  108. resolve(asset as T);
  109. }
  110. }
  111. );
  112. });
  113. }
  114. /**
  115. * 加载目录下所有资源的辅助方法
  116. * @param bundle 资源所在的分包
  117. * @param path 目录路径
  118. * @param onProgress 进度回调函数
  119. * @param onComplete 完成回调函数
  120. * @returns Promise<Array<Asset>> 加载完成后的Promise
  121. */
  122. private loadAssetDir(
  123. bundle: AssetManager.Bundle,
  124. path: string,
  125. onProgress?: (completedCount: number, totalCount: number, item: any) => void,
  126. onComplete?: (err: Error | null, assets: Array<Asset>) => void
  127. ): Promise<Array<Asset>> {
  128. return new Promise<Array<Asset>>((resolve, reject) => {
  129. bundle.loadDir(
  130. path,
  131. (completedCount, totalCount, item) => onProgress?.(completedCount, totalCount, item),
  132. (err, assets) => {
  133. onComplete?.(err, assets);
  134. if (err) {
  135. console.error(`从分包加载目录 ${path} 失败`, err.message);
  136. reject(err);
  137. } else {
  138. resolve(assets);
  139. }
  140. }
  141. );
  142. });
  143. }
  144. /**
  145. * 解析资源路径并将其分解为包名和路径
  146. *
  147. * @param resPath - 要解析的资源路径
  148. * @returns 返回包含 bundleName 和 path 的对象
  149. */
  150. private path(resPath: string): { bundleName: string; path: string } {
  151. const [bundleName, ...pathParts] = resPath.split('/');
  152. return {
  153. bundleName,
  154. path: pathParts.join('/')
  155. };
  156. }
  157. }
  158. /** 资源管理器实例 */
  159. export const resMgr = ResMgr.instance;