当前位置:   article > 正文

unity内存优化之AB包篇(微信小游戏)_unity 微信小游戏

unity 微信小游戏

1.搭建资源服务器使用(HFS软件(https://www.pianshen.com/article/54621708008/))

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. public class Singleton<T> where T : class, new()
  6. {
  7. private static readonly Lazy<T> lazy = new Lazy<T>(() => new T());
  8. public static T Instance { get { return lazy.Value; } }
  9. protected Singleton() { }
  10. }
  11. public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
  12. {
  13. private static T _instance;
  14. public static T Instance
  15. {
  16. get
  17. {
  18. return _instance;
  19. }
  20. }
  21. protected virtual void Awake()
  22. {
  23. _instance = this as T;
  24. }
  25. }

2.核心代码

  1. using Cysharp.Threading.Tasks;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Xml.Linq;
  5. using UnityEngine;
  6. using UnityEngine.Networking;
  7. using UnityEngine.U2D;
  8. /*
  9. 内存优化之AB包篇(微信小游戏)
  10. 问题:如何优化AB包占用的内存,游戏的AB包资源卸载策略是什么
  11. 答:卸载时机
  12. 1.该AB包被引用次数为0时候,此时缓存一定的时间,当缓存时间为0时,就可以调用bundle.Unload(true);
  13. 缓存时间内被调用重置缓存时间,引用次数增加。
  14. 这部分主要用来处理偶尔打开的界面
  15. 2.首先维护一个已经加载的AB包资源大小总值,然后设置一个内存基准值,当总值大于内存基准值的时候,
  16. 此时去卸载那些引用次数为0的ab资源(优先卸载加载早的ab包资源)。
  17. 这部分用来处理短时间内,玩家打开过多大型界面场景,如果不这么处理,手机内存会占用高且发热会严重。
  18. 引用次数的维护时机(引用次数始终不小于0)
  19. 1.例如一张图片 更换属于不同ab包的资源图片时,需要先将旧的ab包 引用次数减一,界面销毁时,最后动态加载的ab图片资源也需要减一,其他资源同理
  20. 2.同时加载一个AB资源时,在AB资源未加载完毕前,需要维护一个加载中的AB包资源实际被加载次数,
  21. 由于部分界面 正在动态加载的ab包资源未加载完毕时,此界面就可能已经被销毁,如果被销毁就需要将加载中的ab包的实际被加载次数减一。
  22. 3.当ab包资源加载完毕时,如果发现加载中的此ab包维护的实际被加载次数大于0,此时ab包的引用次数加一,同时实际被加载次数减一。
  23. 4.当界面销毁时,此界面的ab包和相关依赖的引用次数需要减一,动态加载的ab包资源也需要将引用次数减一
  24. 5.!!!需要注意的是 当A依赖于B时, A的最后一个实例被销毁时 A的引用变为0 但是B的引用此刻不变,除非A被卸载 才能将B的引用减一
  25. // A依赖于B
  26. // A被加载 会先加载B
  27. //那么A引用为1 B引用为1
  28. //A被加载第二次 A引用为2 B引用为2
  29. //A被加载第3次 A引用为3 B引用为3
  30. // A被删除1次 引用为2 B引用为2
  31. //A被删除第二次 A引用为1 B引用为1
  32. //A被删除第3次 A引用为0 B引用为1
  33. //A被卸载时 B引用为0
  34. // A依赖于B
  35. // A被加载 会先加载B
  36. //那么A引用为1 B引用为1
  37. //A被加载第二次 A引用为2 B引用为2
  38. // A被删除1次 引用为1 B引用为1
  39. //A被删除第二次 A引用为0 B引用为1
  40. //A被卸载时 B引用为0
  41. // A依赖于B
  42. // A被加载 会先加载B
  43. //那么A引用为1 B引用为1
  44. // A被删除1次 A引用为0 B引用为1
  45. //A被卸载时 B引用为0
  46. */
  47. [SelectionBase]
  48. public class LoadingAssetBundle
  49. {
  50. private string abName;
  51. public string GetABName()
  52. {
  53. return abName;
  54. }
  55. private int realLoadedTimesInLoading = 0;//在加载中 被加载的真实次数(也就是剔除那些只加载不使用的部分,例如界面动态加载图片还没加载完毕 这个界面就被销毁了)
  56. public int GetRealLoadedTimesInLoading()
  57. {
  58. return realLoadedTimesInLoading;
  59. }
  60. public void AddRealLoadedTimesInLoading()
  61. {
  62. realLoadedTimesInLoading++;
  63. }
  64. public void ReduceRealLoadedTimesInLoading()
  65. {
  66. realLoadedTimesInLoading--;
  67. }
  68. public LoadingAssetBundle(string _abName)
  69. {
  70. abName = _abName;
  71. AddRealLoadedTimesInLoading();
  72. }
  73. }
  74. [SelectionBase]
  75. public class LoadedAssetBundle
  76. {
  77. private string abName;
  78. private AssetBundle bundle;
  79. private float cacheTimeBySenconds = 10;//缓存秒数不同ab可配置
  80. public float curLastCacheTime = 10;//当前剩余缓存时间
  81. public int referenceTimes = 0;//引用次数
  82. public long memoryValue = 0;//ab包大小
  83. public int loadIndexOrder = 0;//引用顺序 越小代表越早被引用
  84. private bool isUnload = false;//是否被卸载
  85. public LoadedAssetBundle(string _abName, AssetBundle _bundle, long _memoryValue, int _loadIndexOrder)
  86. {
  87. isUnload = false;
  88. abName = _abName;
  89. bundle = _bundle;
  90. memoryValue = _memoryValue;//long size = long.Parse(unityWebRequest.GetResponseHeader("Content-Length"));
  91. ABManager.Instance.AddMemoryValue(_memoryValue);
  92. loadIndexOrder = _loadIndexOrder;
  93. }
  94. public AssetBundle GetAssetBundle()
  95. {
  96. return bundle;
  97. }
  98. public void AddRefer()//添加引用1
  99. {
  100. referenceTimes = referenceTimes + 1;
  101. curLastCacheTime = cacheTimeBySenconds;//重置剩余缓存1时间时间
  102. }
  103. public int ReduceRefer()//减少引用
  104. {
  105. if (referenceTimes > 0) {
  106. referenceTimes--;
  107. };
  108. return referenceTimes;
  109. }
  110. public void RefreshCacheLastTime(float time)
  111. {
  112. if (referenceTimes == 0)
  113. {
  114. curLastCacheTime -= time;
  115. CheckCacheTimeUnload();
  116. }
  117. }
  118. private void CheckCacheTimeUnload()
  119. {
  120. if (isUnload) return;
  121. if (curLastCacheTime <= 0&& referenceTimes == 0) {
  122. bundle.Unload(true); //卸载时机1
  123. isUnload = true;
  124. ABManager.Instance.ReduceMemoryValue(memoryValue);
  125. ABManager.Instance.RemoveABRequest(abName);
  126. ABManager.Instance.ReduceDependciedRefer(abName);
  127. Debug.Log($"curLastCacheTime Unload{abName},Count={ABManager.Instance.cachedLoadedDic.Count}");
  128. }
  129. }
  130. public void CheckOverMemoryUnload(int curMinReferIndexOrder)
  131. {
  132. if (isUnload) return;
  133. if (referenceTimes == 0 && ABManager.Instance.CheckOverMemoryMemoryReferenceValue())//&& curMinReferIndexOrder == loadIndexOrder
  134. {
  135. bundle.Unload(true);//卸载时机2
  136. isUnload = true;
  137. ABManager.Instance.ReduceMemoryValue(memoryValue);
  138. ABManager.Instance.RemoveABRequest(abName);
  139. ABManager.Instance.ReduceDependciedRefer(abName);
  140. Debug.Log($"Unload{abName}");
  141. }
  142. }
  143. public string GetABName()
  144. {
  145. return abName;
  146. }
  147. public bool IsUnLoad()
  148. {
  149. return isUnload;
  150. }
  151. }
  152. public class ABManager : MonoSingleton<ABManager>
  153. {
  154. public Dictionary<string, LoadedAssetBundle> cachedLoadedDic = new Dictionary<string, LoadedAssetBundle>();
  155. private Dictionary<string, LoadingAssetBundle> cachedLoadingDic = new Dictionary<string, LoadingAssetBundle>();
  156. private long memoryReferenceValue= 995406;//内存基准值
  157. private long curMemoryValue = 0;//内存当前值
  158. private int curReferIndexOrder = 0;//当前索引
  159. private int curMinReferIndexOrder = 0;//当前被加载最早的索引
  160. public void AddMemoryValue(long _memoryValue)
  161. {
  162. curMemoryValue = curMemoryValue + _memoryValue;
  163. //print("curMemoryValue" + curMemoryValue);
  164. }
  165. public void ReduceMemoryValue(long _memoryValue)
  166. {
  167. //Debug.Log("memoryValue" + _memoryValue);
  168. curMemoryValue = curMemoryValue - _memoryValue;
  169. curMinReferIndexOrder++;
  170. if (curMinReferIndexOrder > curReferIndexOrder)
  171. {
  172. curMinReferIndexOrder = curReferIndexOrder;
  173. }
  174. }
  175. public bool CheckOverMemoryMemoryReferenceValue()
  176. {
  177. return curMemoryValue > memoryReferenceValue;
  178. }
  179. private float checkSpan = 0.3f;
  180. public float time;
  181. List<string> removeList = new List<string>();
  182. public int CachedLoadedCount;
  183. private void CheckUnLoadCachedLoaded()
  184. {
  185. time += Time.fixedDeltaTime;
  186. if (time > checkSpan)
  187. {
  188. time = 0;
  189. removeList.Clear();
  190. foreach (var item in cachedLoadedDic)
  191. {
  192. if (!cachedLoadingDic.ContainsKey(item.Key))
  193. {
  194. item.Value.RefreshCacheLastTime(checkSpan);
  195. item.Value.CheckOverMemoryUnload(curMinReferIndexOrder);
  196. if (item.Value.IsUnLoad()) removeList.Add(item.Key);
  197. }
  198. }
  199. for (int i = 0; i < removeList.Count; i++)
  200. {
  201. print($"removeList={removeList[i]}");
  202. cachedLoadedDic.Remove(removeList[i]);
  203. }
  204. }
  205. CachedLoadedCount = cachedLoadedDic.Count;
  206. }
  207. // Update is called once per frame
  208. void FixedUpdate()
  209. {
  210. CheckUnLoadCachedLoaded();
  211. }
  212. private AssetBundle mainAB = null; //主包
  213. private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包
  214. private string basePath = "http://192.168.31.208/AssetBundles/";
  215. private string mainABName = "AssetBundles";
  216. public Dictionary<string, string> AssetNameToABName = new Dictionary<string, string>();
  217. public async UniTask<GameObject> LoadAsset(string assetName)
  218. {
  219. string abName = assetName.ToLower() + ".ab";
  220. AssetBundle ab = await LoadABPackage(abName);
  221. //await UniTask.SwitchToMainThread();
  222. return ab.LoadAsset<GameObject>(assetName);
  223. }
  224. /// <summary>
  225. /// 加载图集里面的图片
  226. /// 案例
  227. /// Image a = nul;;
  228. /// if (a != null)
  229. /// ABManager.Instance.UnloadAsset(a);
  230. /// a = ABManager.Instance.LoadAtlasSprite(a);
  231. /// </summary>
  232. /// <param name="assetName"></param>
  233. /// <param name="textureName"></param>
  234. /// <returns></returns>
  235. public async UniTask<Sprite> LoadAtlasSprite(string assetName, string textureName)
  236. {
  237. string abName = assetName.ToLower() + ".ab";
  238. AssetBundle ab = await LoadABPackage(abName);
  239. SpriteAtlas spriteAtlas = ab.LoadAsset<SpriteAtlas>(assetName);
  240. return spriteAtlas.GetSprite(textureName);
  241. }
  242. //单个包卸载
  243. public void ReduceRefer(string assetName)
  244. {
  245. string abName = assetName.ToLower() + ".ab";
  246. if (cachedLoadingDic.ContainsKey(abName))
  247. {
  248. cachedLoadingDic[abName].ReduceRealLoadedTimesInLoading();
  249. }
  250. else
  251. {
  252. //--引用
  253. if (cachedLoadedDic.ContainsKey(abName))
  254. {
  255. int referValue = cachedLoadedDic[abName].ReduceRefer();
  256. // A依赖于B
  257. // A被加载 会先加载B
  258. //那么A引用为1 B引用为1
  259. //A被加载第二次 A引用为2 B引用为2
  260. //A被加载第3次 A引用为3 B引用为3
  261. // A被删除1次 引用为2 B引用为2
  262. //A被删除第二次 A引用为1 B引用为1
  263. //A被删除第3次 A引用为0 B引用为1
  264. //A被卸载时 B引用为0
  265. // A依赖于B
  266. // A被加载 会先加载B
  267. //那么A引用为1 B引用为1
  268. //A被加载第二次 A引用为2 B引用为2
  269. // A被删除1次 引用为1 B引用为1
  270. //A被删除第二次 A引用为0 B引用为1
  271. //A被卸载时 B引用为0
  272. // A依赖于B
  273. // A被加载 会先加载B
  274. //那么A引用为1 B引用为1
  275. // A被删除1次 A引用为0 B引用为1
  276. //A被卸载时 B引用为0
  277. if (referValue > 0)
  278. {
  279. ReduceDependciedRefer(abName);
  280. }
  281. }
  282. }
  283. }
  284. public void ReduceDependciedRefer(string abName)
  285. {
  286. string[] dependencies = mainManifest.GetAllDependencies(abName);
  287. for (int i = 0; i < dependencies.Length; i++)
  288. {
  289. if (cachedLoadedDic.ContainsKey(dependencies[i]))
  290. {
  291. cachedLoadedDic[dependencies[i]].ReduceRefer();
  292. }
  293. }
  294. }
  295. //加载AB包
  296. private async UniTask<AssetBundle> LoadABPackage(string abName)
  297. {
  298. //加载ab包,需一并加载其依赖包。
  299. if (mainAB == null)
  300. {
  301. //获取ab包内容
  302. mainAB = await DownloadABPackage(mainABName);
  303. //获取主包下的AssetBundleManifest资源文件(存有依赖信息)
  304. mainManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  305. }
  306. //根据manifest获取所有依赖包的名称 固定API 保证不丢失依赖
  307. string[] dependencies = mainManifest.GetAllDependencies(abName);
  308. if (dependencies.Length > 0)
  309. {
  310. var tasks = new List<UniTask>(); // 创建一个任务列表来存储异步操作
  311. //循环加载所有依赖包
  312. for (int i = 0; i < dependencies.Length; i++)
  313. {
  314. //如果不在缓存则加入
  315. if (!cachedLoadedDic.ContainsKey(dependencies[i]))
  316. tasks.Add(LoadABPackage(dependencies[i]));
  317. else
  318. {
  319. cachedLoadedDic[dependencies[i]].AddRefer(); //++引用
  320. }
  321. }
  322. // 使用UniTask.WhenAll等待所有任务完成
  323. await UniTask.WhenAll(tasks);
  324. }
  325. //加载目标包 -- 同理注意缓存问题
  326. if (cachedLoadedDic.ContainsKey(abName))
  327. {
  328. cachedLoadedDic[abName].AddRefer(); //++引用
  329. Debug.Log($"ContainsKey{abName}");
  330. return (cachedLoadedDic[abName].GetAssetBundle());
  331. }
  332. else
  333. {
  334. await DownloadABPackage(abName);
  335. Debug.Log($"DownloadABPackage{abName}");
  336. return (cachedLoadedDic[abName].GetAssetBundle());
  337. }
  338. }
  339. //存儲下載操作
  340. Dictionary<string, UnityWebRequestAsyncOperation> ABRequestOpera = new Dictionary<string, UnityWebRequestAsyncOperation>();
  341. public void RemoveABRequest(string abname)
  342. {
  343. string url = basePath + abname;
  344. ABRequestOpera[url].webRequest.Dispose();//试试多个异步创建
  345. ABRequestOpera.Remove(url);
  346. }
  347. async UniTask<AssetBundle> DownloadABPackage(string abname)
  348. {
  349. if (cachedLoadedDic.ContainsKey(abname))
  350. {
  351. cachedLoadedDic[abname].AddRefer();
  352. return cachedLoadedDic[abname].GetAssetBundle();
  353. }
  354. string url = basePath + abname;
  355. Debug.Log(url);
  356. if (!cachedLoadingDic.ContainsKey(abname))
  357. {
  358. cachedLoadingDic.Add(abname, new LoadingAssetBundle(abname));
  359. }
  360. else
  361. {
  362. cachedLoadingDic[abname].AddRealLoadedTimesInLoading();
  363. }
  364. if (!ABRequestOpera.ContainsKey(url))
  365. {
  366. UnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle(url);
  367. UnityWebRequestAsyncOperation operation = req.SendWebRequest();
  368. ABRequestOpera.Add(url, operation);
  369. }
  370. await ABRequestOpera[url];
  371. if (!cachedLoadedDic.ContainsKey(abname))
  372. {
  373. curReferIndexOrder++;
  374. AssetBundle ab = DownloadHandlerAssetBundle.GetContent(ABRequestOpera[url].webRequest);
  375. long size = long.Parse(ABRequestOpera[url].webRequest.GetResponseHeader("Content-Length"));
  376. cachedLoadedDic.Add(abname, new LoadedAssetBundle(abname,ab, size, curReferIndexOrder));
  377. }
  378. if (cachedLoadingDic.ContainsKey(abname)&&cachedLoadingDic[abname].GetRealLoadedTimesInLoading() > 0)
  379. {
  380. cachedLoadedDic[abname].AddRefer();
  381. cachedLoadingDic[abname].ReduceRealLoadedTimesInLoading();
  382. if (cachedLoadingDic[abname].GetRealLoadedTimesInLoading() == 0)
  383. {
  384. cachedLoadingDic.Remove(abname);
  385. }
  386. }
  387. return cachedLoadedDic[abname].GetAssetBundle();
  388. }
  389. //所有包卸载
  390. public void UnLoadAll()
  391. {
  392. AssetBundle.UnloadAllAssetBundles(false);
  393. //注意清空缓存
  394. cachedLoadedDic.Clear();
  395. cachedLoadingDic.Clear();
  396. mainAB = null;
  397. mainManifest = null;
  398. }
  399. }

3..打包AB包代码

  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.IO;
  4. using System;
  5. using System.Collections.Generic;
  6. /// <summary>
  7. /// AB包创建
  8. /// </summary>
  9. public class CreateAssetBundles : MonoBehaviour
  10. {
  11. public static string BuildAssetBundlePath = Application.dataPath + "/AssetsPach/AssetBundles";
  12. [MenuItem("Build/BuildAssetBundles")]
  13. public static void BuildAssetBundle()
  14. {
  15. SetAssetBundle();
  16. string dir = BuildAssetBundlePath; //相对路径
  17. if (!Directory.Exists(dir)) //判断路径是否存在
  18. {
  19. Directory.CreateDirectory(dir);
  20. }
  21. BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget); //这里是第一点注意事项,BuildTarget类型选择WebGL
  22. AssetDatabase.Refresh();
  23. Debug.Log("打包完成");
  24. }
  25. //需要打包的资源目录
  26. public static string SetAssetBundlePath = Application.dataPath + "/AssetsPach/WortAsset";
  27. public static void SetAssetBundle()
  28. {
  29. string dir = SetAssetBundlePath; //相对路径
  30. AssetDatabase.RemoveUnusedAssetBundleNames();//移除无用的AssetBundleName
  31. //Debug.LogError(Application.dataPath);//上级路径 F:/TUANJIEProject/My project/Assets
  32. list_Files = new List<stru_FileInfo>();
  33. ContinueCheck(dir);
  34. for (int a = 0; a < list_Files.Count; a++)//
  35. {
  36. SetBundleName(list_Files[a].assetPath);
  37. }
  38. Debug.Log("生成ab包完成");
  39. //SetBundleName("Assets/Ship/AC_Enterprise_T01/prefab/AC_Enterprise_T01_M01_ShipMesh.prefab");
  40. }
  41. //******资源参数
  42. static List<stru_FileInfo> list_Files;//文件列表
  43. static string assetBundleName = "ab";
  44. static string assetBundleVariant = "";
  45. //int indentation;//缩进等级
  46. struct stru_FileInfo
  47. {
  48. public string fileName;
  49. public string filePath;//绝对路径
  50. public string assetPath;//U3D内部路径
  51. public Type assetType;
  52. }
  53. static void ContinueCheck(string path)
  54. {
  55. DirectoryInfo directory = new DirectoryInfo(path);
  56. FileSystemInfo[] fileSystemInfos = directory.GetFileSystemInfos();//获取文件夹下的文件信息
  57. foreach (var item in fileSystemInfos)
  58. {
  59. int idx = item.ToString().LastIndexOf(@"\");
  60. string name = item.ToString().Substring(idx + 1);
  61. if (!name.Contains(".meta"))//剔除meta文件
  62. {
  63. CheckFileOrDirectory(item, path + "/" + name);
  64. }
  65. }
  66. }
  67. static void CheckFileOrDirectory(FileSystemInfo fileSystemInfo, string path)
  68. {
  69. FileInfo fileInfo = fileSystemInfo as FileInfo;
  70. if (fileInfo != null)
  71. {
  72. stru_FileInfo t_file = new stru_FileInfo();
  73. t_file.fileName = fileInfo.Name;
  74. t_file.filePath = fileInfo.FullName;
  75. t_file.assetPath = "Assets" + fileInfo.FullName.Replace(Application.dataPath.Replace("/", "\\"), "");//用于下一步获得文件类型
  76. t_file.assetType = AssetDatabase.GetMainAssetTypeAtPath(t_file.assetPath);
  77. list_Files.Add(t_file);
  78. }
  79. else
  80. {
  81. ContinueCheck(path);
  82. }
  83. }
  84. static void SetBundleName(string path)
  85. {
  86. print(path);
  87. var importer = AssetImporter.GetAtPath(path);
  88. string[] strs = path.Split(".");
  89. string[] dictors = strs[0].Split('/');
  90. if (importer)
  91. {
  92. if (assetBundleVariant != "")
  93. {
  94. importer.assetBundleVariant = assetBundleVariant;
  95. }
  96. if (assetBundleName != "")
  97. {
  98. importer.assetBundleName = path.ToLower() + "." + assetBundleName;
  99. }
  100. }
  101. else
  102. {
  103. Debug.Log("importer是空的" + path);//jpg png tga
  104. }
  105. }
  106. }

4.资源如下 几张美女壁纸,每个预设都是一个壁纸和关闭按钮界面挂载了代码

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class Panel : MonoBehaviour
  6. {
  7. public string asssetName;
  8. // Start is called before the first frame update
  9. void Start()
  10. {
  11. transform.GetComponentInChildren<Button>().onClick.AddListener(() => {
  12. //StartCoroutine(TestLoadSize();
  13. UIManager.Instance.DeletePanel(this);
  14. });
  15. }
  16. // Update is called once per frame
  17. void Update()
  18. {
  19. }
  20. }

4.启动场景和代码

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class UIManager : MonoSingleton<UIManager>
  6. {
  7. public Transform parent;
  8. // Start is called before the first frame update
  9. void Start()
  10. {
  11. for (int i = 0; i < transform.childCount; i++)
  12. {
  13. int index = i;
  14. transform.GetChild(i).GetComponent<Button>().onClick.AddListener(() => {
  15. //StartCoroutine(TestLoadSize();
  16. print(111);
  17. DownPanel($"Assets/Assetspach/wortasset/prefabs/Panel{index + 1}.prefab");
  18. //DownPanel($"Assets/Assetspach/wortasset/prefabs/Panel{index + 1}.prefab");
  19. });
  20. }
  21. }
  22. async void DownPanel(string asssetName)
  23. {
  24. GameObject go = await ABManager.Instance.LoadAsset(asssetName);
  25. GameObject.Instantiate(go, parent).GetComponent<Panel>().asssetName =asssetName;
  26. }
  27. // Update is called once per frame
  28. public void DeletePanel(Panel panel)
  29. {
  30. ABManager.Instance.ReduceRefer(panel.asssetName);
  31. DestroyImmediate(panel.gameObject);
  32. }
  33. }

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

闽ICP备14008679号