unityAB包管理(远程下载)

1.AB包生成脚本

using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using System.Collections.Generic;/// <summary>
/// AB包创建
/// </summary>
public class CreateAssetBundles : MonoBehaviour
{public static string BuildAssetBundlePath = Application.dataPath + "/AssetsPach/AssetBundles";public static void BuildAssetBundle_WeixinMiniGame(){string dir = BuildAssetBundlePath; //相对路径if (!Directory.Exists(dir))   //判断路径是否存在{Directory.CreateDirectory(dir);}BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.WeixinMiniGame); //这里是第一点注意事项,BuildTarget类型选择WebGLAssetDatabase.Refresh();Debug.Log("打包完成");}//需要打包的资源目录public static string SetAssetBundlePath = Application.dataPath + "/AssetsPach/WortAsset";public static void SetAssetBundle_WeixinMiniGame(){string dir = SetAssetBundlePath; //相对路径AssetDatabase.RemoveUnusedAssetBundleNames();//移除无用的AssetBundleName//Debug.LogError(Application.dataPath);//上级路径 F:/TUANJIEProject/My project/Assetslist_Files = new List<stru_FileInfo>();ContinueCheck(dir);for (int a = 0; a < list_Files.Count; a++)//{SetBundleName(list_Files[a].assetPath);}Debug.Log("生成ab包完成");//SetBundleName("Assets/Ship/AC_Enterprise_T01/prefab/AC_Enterprise_T01_M01_ShipMesh.prefab");}//******资源参数static List<stru_FileInfo> list_Files;//文件列表static string assetBundleName = "ab";static string assetBundleVariant = "";//int indentation;//缩进等级struct stru_FileInfo{public string fileName;public string filePath;//绝对路径public string assetPath;//U3D内部路径public Type assetType;}static void ContinueCheck(string path){DirectoryInfo directory = new DirectoryInfo(path);FileSystemInfo[] fileSystemInfos = directory.GetFileSystemInfos();//获取文件夹下的文件信息foreach (var item in fileSystemInfos){int idx = item.ToString().LastIndexOf(@"\");string name = item.ToString().Substring(idx + 1);if (!name.Contains(".meta"))//剔除meta文件{CheckFileOrDirectory(item, path + "/" + name);}}}static void CheckFileOrDirectory(FileSystemInfo fileSystemInfo,string path){FileInfo fileInfo = fileSystemInfo as FileInfo;if (fileInfo != null){stru_FileInfo t_file = new stru_FileInfo();t_file.fileName = fileInfo.Name;t_file.filePath = fileInfo.FullName;t_file.assetPath = "Assets" + fileInfo.FullName.Replace(Application.dataPath.Replace("/", "\\"), "");//用于下一步获得文件类型t_file.assetType = AssetDatabase.GetMainAssetTypeAtPath(t_file.assetPath);list_Files.Add(t_file);}else{ContinueCheck(path);}}static void SetBundleName(string path){var importer = AssetImporter.GetAtPath(path);string[] strs = path.Split(".");string[] dictors = strs[0].Split('/');if (importer){if (assetBundleVariant != ""){importer.assetBundleVariant = assetBundleVariant;}if (assetBundleName != ""){importer.assetBundleName = path.ToLower() + "." + assetBundleName;}}else{Debug.Log("importer是空的"+ path);//jpg  png tga}}}

2.AB包管理类

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

using System;
using System.Net.Mime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
using Cysharp.Threading.Tasks; // 首先需要引入UniTask插件
using UnityEngine.Networking;
using UnityEngine.U2D;//已经加载的AB类
public class LoadedAssetBundle
{public AssetBundle bundle;public string abName;public int referenceCount = 0;public void AddRefer(){referenceCount++;}public int Decrease(){referenceCount--;if (referenceCount <= 0) referenceCount = 0;return referenceCount;}}/// <summary>
/// AB包管理器 全局唯一 使用单例模式
/// 
/// 需要有的功能
/// 1.资源名索引ab包名 的字典
/// 2.私有方法 通过资源名下载AB包,同时下载一个AB包时 会同时等待,已经存AB缓存 以防多次下载同一个AB包
/// 3.通过资源名 加载 预制体加载范例
/// 4.通过图集名,图片名 加载 通过TexturePacker创建的图集,如果需要访问图集的精灵对象,可以通过子对象加载接口。
/// 5.需要常驻的AB包 比如字体库  通用图集  不需要卸载
/// 
/// 
/// </summary>
public class ABManager
{private static readonly Lazy<ABManager> lazy = new Lazy<ABManager>(() => new ABManager());public static ABManager Instance { get { return lazy.Value; } }private ABManager() { Init(); }//AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。private Dictionary<string, LoadedAssetBundle> abCache;private AssetBundle mainAB = null; //主包private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包private string basePath = "https://xxx/gh5_test/StreamingAssets/AssetBundles/";private string mainABName = "AssetBundles";//继承了单例模式提供的初始化函数void Init(){//初始化字典abCache = new Dictionary<string, LoadedAssetBundle>();}public Dictionary<string, string> AssetNameToABName = new Dictionary<string, string>();public async UniTask<GameObject> LoadAsset(string assetName){string abName = assetName.ToLower() + ".ab";AssetBundle ab = await LoadABPackage(abName);return ab.LoadAsset<GameObject>(assetName);}/// <summary>/// 加载图集里面的图片/// 案例///   Image a = nul;;///   if (a != null)///        ABManager.Instance.UnloadAsset(a);///    a = ABManager.Instance.LoadAtlasSprite(a);/// </summary>/// <param name="assetName"></param>/// <param name="textureName"></param>/// <returns></returns>public async UniTask<Sprite> LoadAtlasSprite(string assetName,string textureName){string abName = assetName.ToLower() + ".ab";AssetBundle ab = await LoadABPackage(abName);SpriteAtlas spriteAtlas = ab.LoadAsset<SpriteAtlas>(assetName);   return spriteAtlas.GetSprite(textureName);}//单个包卸载public void UnloadAsset(string assetName){string abName = assetName.ToLower() + ".ab";//--引用if (abCache.ContainsKey(abName)){int reference = abCache[abName].Decrease();if (reference == 0){abCache[abName].bundle.Unload(true);//注意缓存需一并移除abCache.Remove(abName);}}}//加载AB包private async UniTask<AssetBundle> LoadABPackage(string abName){//加载ab包,需一并加载其依赖包。if (mainAB == null){//获取ab包内容mainAB = await DownloadABPackage(mainABName);         //获取主包下的AssetBundleManifest资源文件(存有依赖信息)mainManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");}//加载目标包 -- 同理注意缓存问题if (abCache.ContainsKey(abName)){           abCache[abName].AddRefer(); //++引用return (abCache[abName].bundle);}else{//根据manifest获取所有依赖包的名称 固定APIstring[] dependencies = mainManifest.GetAllDependencies(abName);if (dependencies.Length > 0){var tasks = new List<UniTask>(); // 创建一个任务列表来存储异步操作//循环加载所有依赖包for (int i = 0; i < dependencies.Length; i++){//如果不在缓存则加入if (!abCache.ContainsKey(dependencies[i])) tasks.Add(LoadABPackage(dependencies[i]));}// 使用UniTask.WhenAll等待所有任务完成await UniTask.WhenAll(tasks);}await DownloadABPackage(abName);abCache[abName].AddRefer(); //++引用return (abCache[abName].bundle);}}//存儲下載操作Dictionary<string, UnityWebRequestAsyncOperation> ABRequest = new Dictionary<string, UnityWebRequestAsyncOperation>();async UniTask<AssetBundle> DownloadABPackage(string abname){if (abCache.ContainsKey(abname))return abCache[abname].bundle;string url = basePath + abname;Debug.Log(url);if (!ABRequest.ContainsKey(url)){UnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle(url);UnityWebRequestAsyncOperation operation = req.SendWebRequest();ABRequest.Add(url, operation);}await ABRequest[url];if (!abCache.ContainsKey(abname)){AssetBundle ab = DownloadHandlerAssetBundle.GetContent(ABRequest[url].webRequest);abCache.Add(abname, new LoadedAssetBundle() { abName = abname, bundle = ab });ABRequest.Remove(abname);ABRequest[url].webRequest.Dispose();}return abCache[abname].bundle;}//所有包卸载public void UnLoadAll(){AssetBundle.UnloadAllAssetBundles(false);//注意清空缓存abCache.Clear();mainAB = null;mainManifest = null;}}
/**UnityWebRequest[AssetBundle].GetAssetBundle()
适用于从远程下载AssetBundle
能够缓存已下载的AssetBundle以便重用
缓存系统中的AssetBundle仅以文件名进行标识而不是使用URL
1.强烈建议开发者不要在WebGL项目中使用压缩的AssetBundle
2.注意:然而对于大多数项目而言,这种行为是不可取的。大多数项目应该使用AssetBundle.Unload(true)并采用一种方法来确保对象不重复。两种常用方法是:
(1)在应用程序的生命周期中设置一些卸载资源绑定的节点,例如场景切换时。
(2)维护单个对象的引用计数,并仅在其所有组成对象都未使用时卸载资产绑定。这允许应用程序卸载和重新加载单个对象,而无需复制内存。
3.ab包的卸載
如O是某资源,如果调用AssetBundle.Unload(true),那么M将从场景中移除、销毁并卸载。
但是,如果调用AssetBundle.Unload(false),则AB的头信息将被卸载,但O将保留在场景中,
并且仍然可以正常工作。调用AssetBundle.Unload(false)会中断O和AB之间的链接。
如果以后再次加载AB,则AB中包含的对象的新副本将加载到内存中。
如果以后再次加载AB,则会重新加载资产绑定头信息的新副本。
但是,O不是从AB的新副本加载的。Unity不会在AB的新副本和O之间建立任何链接。 
如果调用AssetBundle.LoadAsset()重新加载O,Unity将不会将O的旧副本解释为AB中数据的实例。
因此,Unity将加载O的新副本,并且场景中将有两个相同的O副本。
4.CRC校验
AB包加载资源的完整方法实际上是AssetBundle.LoadFromFile(string path, uint crc, ulong offset),
三个参数。其中第二个参数就是CRC校验符。
每个AB包的.manifest文件中也有CRC校验符,用于校验数据完整性。
5.状态维护  AB加载的过程中  其他地方可能同时也在加载  需要维护AB的状态  加载中  加载完成  是否被使用
6.回调维护  同时多个加载AB包 不同地方的回调
7.在游戏中会存在大量的ab包资源,如果这些都加载在内存中,不卸载那么很有可能会造成游戏崩溃。就像一个容器只往里添加而不往外拿,
那么再大的容器也会被撑满。所以ab包什么时候卸载,卸载哪些包,就会是一个大问题。本文使用引用计数的方法解决ab包资源的管理问题。
(https://blog.csdn.net/qq_38399916/article/details/135643315)*/

3.使用案例

using Cysharp.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;public class GameEntrance : MonoBehaviour
{// Start is called before the first frame updateasync void  Start(){GameObject go =  await  ABManager.Instance.LoadAsset("Assets/AssetsPach/Wortasset/Prefabs/Canvas.prefab");GameObject.Instantiate(go);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/741502.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARM 汇编指令:(五)CMP指令

目录 1.CMP比较指令 2.指令条件码 cond 1.CMP比较指令 CMP指令是计算机指令集中的一种比较指令&#xff0c;用于比较两个操作数的大小关系或相等性&#xff0c;并根据比较结果设置或更新条件码寄存器&#xff08;或程序状态字&#xff09;的标志位。 指令格式&#xff1a;C…

VUE内盘期货配资软件源码国际外盘二合一

开发一个Vue内盘期货配资软件源码&#xff0c;同时兼容国际外盘二合一的功能&#xff0c;是一个复杂且专业的任务&#xff0c;涉及前端Vue.js框架的使用、后端服务器处理、数据库管理、实时交易接口对接等多个方面。下面是一些关于开发此类软件的基本指导和考虑因素&#xff1a…

富格林:洞悉暗箱手法可信策略远离

富格林悉知&#xff0c;在现货黄金中&#xff0c;揭秘很多投资者都是奔着盈利来的&#xff0c;因此学习正规盈利出金技能是必不可少的。但一些投资者在进入市场后并不注意技能的提升&#xff0c;只是一味的看中盈利&#xff0c;这样的做单导致被诱导暗箱亏损的不少&#xff0c;…

什么是同城上门预约按摩系统,上门预约平台有哪些功能?

随着互联网技术的发展&#xff0c;人们的生活方式发生了很大的变化。在日常生活中&#xff0c;大家都习惯使用手机来订餐、购物、家政服务等&#xff0c;这也为我们的生活带来了很大的便利。而同城按摩小程序作为一种新兴的按摩预约方式&#xff0c;受到了越来越多人的欢迎。下…

轻松上手MacOS:HomeBrew安装全指南

轻松上手MacOS&#xff1a;HomeBrew安装全指南 你是否曾为在MacOS上安装软件而烦恼&#xff1f;是否想要一个既强大又简单的包管理器来简化你的安装过程&#xff1f;HomeBrew正是你所需要的工具。作为MacOS上的包管理器&#xff0c;HomeBrew让安装软件变得像数123一样容易。在…

机器视觉检测设备的组成要素

机器视觉检测设备是一种先进的自动化检测技术工具&#xff0c;它利用光学、图像处理和计算机硬件及软件技术模拟并扩展人类的视觉功能&#xff0c;以实现对产品或目标物体进行自动化的尺寸测量、缺陷检测、表面质量评估、颜色识别、形状匹配以及位置判断等功能。这种设备通常包…

GettingStartedwithLLVMCoreLibraries书籍

Getting Started with LLVM Core Libraries 参考1 LLVM是构架编译器(compiler)的框架系统&#xff0c;以C编写而成&#xff0c;用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time)&#xff0c;对开…

c/c++| 常规 |sizeof 、strlen

总结来说 &#xff0c;sizeof 查看内存给对象分配的空间大小&#xff0c;不仅仅是普通的内置变量&#xff0c;还包括用户自定义变量、结构体、类对象 然后strlen 是查看字符串的实际长度大小&#xff0c;注意它不会计算那个结束符’\0’

重生奇迹MU攻击防御技能石哪里掉

在《重生奇迹MU》中&#xff0c;攻击和防御技能石可以从以下途径获得&#xff1a; 1.怪物掉落&#xff1a;你可以通过击败怪物获得攻击和防御技能石&#xff0c;不同的怪物掉落不同的石头。你可以在各个地图的怪物掉落表中查看特定怪物掉落的技能石。 2.商店购买&#xff1a;…

【教程】APP加固的那些小事

摘要 APP加固是保护APP代码逻辑的重要手段&#xff0c;通过隐藏、混淆、加密等操作提高软件的逆向成本&#xff0c;降低被破解的几率&#xff0c;保障开发者和用户利益。本文将介绍APP加固常见失败原因及解决方法&#xff0c;以及处理安装出现问题的情况和资源文件加固策略选择…

eclipse报: cvc-elt.1: Cannot find the declaration of element

eclipse报: cvc-elt.1: Cannot find the declaration of element 这个错误通常出现在XML文件中&#xff0c;它表示XML解析器在尝试解析XML文件时找不到某个元素的声明。这通常是因为XML文件引用的DTD&#xff08;文档类型定义&#xff09;或XSD&#xff08;XML Schema定义&…

怎么查看电脑是不是固态硬盘?简单几个步骤判断

随着科技的发展&#xff0c;固态硬盘&#xff08;Solid State Drive&#xff0c;简称SSD&#xff09;已成为现代电脑的标配。相较于传统的机械硬盘&#xff0c;固态硬盘在读写速度、稳定性和耐用性等方面都有显著优势。但是&#xff0c;对于不熟悉电脑硬件的用户来说&#xff0…

3D地图在BI大屏中的应用实践

前言 随着商业智能的不断发展&#xff0c;数据可视化已成为一项重要工具&#xff0c;有助于用户更好地理解数据和分析结果。其中&#xff0c;3D地图作为一种可视化工具&#xff0c;已经在BI大屏中得到了广泛地应用。 3D地图通过将地理信息与数据相结合&#xff0c;以更加直观…

3. git 回退代码版本

在Git中&#xff0c;如果你想要将某个分支的代码回退到上一个版本&#xff0c;你可以使用 git revert 或者 git reset 命令。 这两个命令有不同的用途和效果&#xff0c;因此你需要根据你的具体需求来选择合适的命令。 使用 git revert git revert 命令用于创建一个新的提交&…

【Linux】Shell编程【一】

shell是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Shell属于内置的…

【C++ 学习】程序内存分布

文章目录 1. C 内存分布的引入 1. C 内存分布的引入 ① 栈又叫堆栈&#xff1a;非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的。 ② 内存映射段&#xff1a;是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存…

Java异常处理神器:Guava Throwables类

Guava由Google开发&#xff0c;它提供了大量的核心Java库&#xff0c;例如&#xff1a;集合、缓存、原生类型支持、并发库、通用注解、字符串处理和I/O操作等。这些功能在日常的Java开发中超级常用&#xff0c;而且Guava的设计哲学是简洁高效&#xff0c;这让咱们的代码不仅更加…

[Django 0-1] Core.Checks 模块

Checks 源码分析 Django 的 checks 模块提供了一系列的检查函数&#xff0c;用于检查 Django 项目的配置是否正确。 文件结构 . ├── __init__.py ├── async_checks.py ├── caches.py ├── compatibility │ ├── __init__.py │ └── django_4_0.py ├─…

【知识库系统】使用SpringSecurity进行身份认证

一、理论知识部分 SpringSecurity 的官网文档地址&#xff1a;SpringSecurity 这里以24年3月份的 6.2.2 版本为例&#xff0c;记录一下学习过程。 1. SpringSecurity 是基于 Servlet Filters 的&#xff0c;而 Servlet Filters 中的流程如下&#xff1a;首先由客户端 Client…

【前端】如何计算首屏及白屏时间

文章目录 一、首屏时间二、白屏时间 一、首屏时间 白屏时间&#xff1a;页面渲染完所有内容的时间 简单点就是在<body> 标签后写js代码计算&#xff0c;但是不是很准确 <head><title>白屏时间</title> </head> <body></body> <s…