unityAB包(2/2)

unityAB包(2/2)

    • unity
      • 1.AB包的依赖问题
      • 2.AB包资源管理器
        • 先导:饿汉模式与懒汉模式
          • 饿汉模式
          • 懒汉模式
        • AB资源管理器主代码

unity

1.AB包的依赖问题

例如一个Prefab被添加到了AB包中,该包会默认添加这个预设体带有的材质等,然而如果你手动把相关的材质添加到了另外的AB包中,此时该材质就不会添加到预设体的AB包中(可能是出于性能考虑机制),则一定要引用预设体对应的包和材质所对应的包,否则会出现材质错误。

然而显而易见的是当这个预设体的引用来自各个不同的AB包中,那么一条一条引入包的代码就会显得很冗余。所以引入了下面这个方法。

通过给定的API得到所有依赖的信息,然后用一个string数组存储这些依赖包的名字,通过遍历依赖名字数组导入所有的依赖。

AssetBundle abMain = AssetBundle.LoadFromFile (Application.streamingAssetsPath + "/" + "PC");
// 加载主包中的固定文件
AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
// 从固定文件中 得到依赖信息
string [] strs = abManifest.GetAllDependencies ("model");
// 得到了 依赖包的名字
for (int i = 0; i < strs.Length; i++)
{AssetBundle.LoadFromFile (Application.streamingAssetsPath+ "/" + strs [i]);
}

这种方法不能对一个AB包中的预设体进行区分,例如A刚需EF包,B刚需OL包,
然而我项目中只使用了A,然而在检查依赖的时候会一同加载不被需要的OL包。

2.AB包资源管理器

先导:饿汉模式与懒汉模式
饿汉模式

在类建立之初就创建一个只读的对象,确保唯一。

using UnityEngine;public class EagerSingleton : MonoBehaviour
{// 静态字段,用于存储单例实例public static EagerSingleton instance;private void Awake(){// 在Awake方法中进行实例的初始化if (instance == null){instance = this;// 确保单例对象在场景切换时不会被销毁DontDestroyOnLoad(gameObject);}else{// 如果已经存在实例,则销毁当前对象Destroy(gameObject);}}
}
懒汉模式

引用自:博主YY-nb直达
确保只有在类的内部才能实例化,外部只能调用Instance方法。
使用lock确保在同一时间内只有一个进程在执行创建单例。
如果后续还有访问这个单例的,直接返回这个单例,不要再继续加锁了,影响性能。

public class Singleton
{private static Singleton instance;private static readonly object locker = new object();private Singleton(){}public static Singleton Instance{get{if (instance == null){lock (locker){if (instance == null)instance = new Singleton();                    }}return instance;}       }
}
AB资源管理器主代码
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;public class AssetBundleManager : MonoBehaviour
{public static AssetBundleManager Instance;private Dictionary<string, AssetBundle> abDic;private AssetBundle mainAB = null;private AssetBundleManifest mainfest = null;public string abUrl { get; private set; }public string mainAbName { get; private set; }private void Awake(){if (Instance == null){Instance = this;DontDestroyOnLoad(gameObject);}else if(Instance != this){Destroy(gameObject);}}private void Start(){abDic = new Dictionary<string, AssetBundle>();abUrl = Application.streamingAssetsPath + "/";mainAbName = "PC";}//加载依赖public void LoadDepends(string abName){//获取主包if(mainAB == null){mainAB = AssetBundle.LoadFromFile(abUrl + mainAbName);        //固定语法 获取AB包配置文件mainfest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");}string[] temp = mainfest.GetAllDependencies(abName);//主包API获取小包的依赖for(int i = 0; i < temp.Length; i++){if (!abDic.ContainsKey(temp[i])){AssetBundle tempab = AssetBundle.LoadFromFile(abUrl + temp[i]);//某个小包 依赖了这么多小包abDic.Add(temp[i], tempab);}else{Debug.Log("again");}}if (!abDic.ContainsKey(abName)){AssetBundle ab = AssetBundle.LoadFromFile(abUrl + abName);abDic.Add(abName, ab);}else{Debug.Log("again");}}// 同步加载public T LoadRes<T>(string abName, string resName) where T : Object{Debug.Log("YSe");LoadDepends(abName);T res = abDic[abName].LoadAsset<T>(resName);return res;}// 异步加载// 异步加载依赖public IEnumerator LoadDependsAsync(string abName){// 获取主包if (mainAB == null){AssetBundleCreateRequest mainABRequest = AssetBundle.LoadFromFileAsync(abUrl + mainAbName);yield return mainABRequest;mainAB = mainABRequest.assetBundle;mainfest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");}//只要涉及获取等待的任务 都需要一个yield returnstring[] temp = mainfest.GetAllDependencies(abName);for (int i = 0; i < temp.Length; i++){if (!abDic.ContainsKey(temp[i])){AssetBundleCreateRequest tempAbRequest = AssetBundle.LoadFromFileAsync(abUrl + temp[i]);yield return tempAbRequest;AssetBundle tempab = tempAbRequest.assetBundle;abDic.Add(temp[i], tempab);}else{Debug.Log("again");}}if (!abDic.ContainsKey(abName)){AssetBundleCreateRequest abRequest = AssetBundle.LoadFromFileAsync(abUrl + abName);yield return abRequest;AssetBundle ab = abRequest.assetBundle;abDic.Add(abName, ab);}else{Debug.Log("again");}}// 异步加载资源public IEnumerator LoadResAsync<T>(string abName, string resName, System.Action<T> onComplete) where T : Object{yield return StartCoroutine(LoadDependsAsync(abName));AssetBundleRequest request = abDic[abName].LoadAssetAsync<T>(resName);yield return request;T res = abDic[abName].LoadAsset<T>(resName);onComplete?.Invoke(res);}// 卸载单个包public void UnLoad(string abName){abDic[abName].Unload(false);abDic.Remove(abName);}// 卸载所有包public void UnLoadAll(){AssetBundle.UnloadAllAssetBundles(false);abDic.Clear();mainAB = null;mainfest = null;}
}

TEST脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){//同步GameObject gameObject = AssetBundleManager.Instance.LoadRes<GameObject>("model", "Cube");Instantiate(gameObject,Vector3.up,Quaternion.identity);GameObject gameObject2 = AssetBundleManager.Instance.LoadRes<GameObject>("model", "Cube");Instantiate(gameObject2, Vector3.down, Quaternion.identity);//异步StartCoroutine(AssetBundleManager.Instance.LoadResAsync<GameObject>("model", "Cube", OnAssetLoaded));}//根据传出类型的不同 编写不同的OnXXX函数,然后订阅此函数private void OnAssetLoaded(GameObject loadedAsset){if (loadedAsset != null){// 资源加载成功,实例化该资源Instantiate(loadedAsset);Debug.Log("资源加载并实例化成功!");}else{Debug.LogError("资源加载失败!");}}// Update is called once per framevoid Update(){}
}

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

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

相关文章

常见中间件漏洞攻略-Apache篇

漏洞名称&#xff1a;Apache HTTP Server 路径穿越漏洞-CVE-2021-41773 第一步&#xff1a;拉取环境、启动环境 #拉取环境 docker pull blueteamsteve/cve-2021-41773:no-cgidhttp://121.40.229.129:8080#启动环境 docker run -dit -p 8080:80 blueteamsteve/cve-2021-41773:n…

站群服务器是什么意思呢?

站群服务器是一种专门为托管和管理多个网站而设计的服务器&#xff0c;其核心特点是为每个网站分配独立的IP地址。这种服务器通常用于SEO优化、提高网站权重和排名&#xff0c;以及集中管理多个网站的需求。以下是站群服务器的详细解释&#xff1a; 一、站群服务器的定义 站群…

Excel 小黑第22套

对应大猫22 新建一行&#xff0c;输入第一个人名字&#xff0c; 填充 -快速填充 修改员工编号&#xff08;1—001&#xff09;&#xff1a;选中所有员工编号&#xff0c;开始 -数据组 -自定义数字格式 000 在所有空表格单元格中输入数字0&#xff1a;选中修改的表格范围&#…

多传感器融合 SLAM LVI-SAM

目录 LVI-SAM 简介 A. 系统概述 B. 视觉惯导系统 C.雷达惯导系统 LVI-SAM 安装编译 编译 LVI-SAM 常见问题 LVI-SAM 工程化建议 LVI-SAM 简介 源码地址:https://github.com/TixiaoShan/LVI-SAM 如无法下载,换用 gitee 版本:https://gitee.com/inf_lee/LVI-SAM 改进…

Linux shell脚本3-if语句、case语句、for语句、while语句、until语句、break语句、continue语句,格式说明及程序验证

目录 1.if 控制语句 1.1 if 语句格式 1.2 程序验证 2.case语句 2.1case语句格式 2.2程序验证 2.2.1 终端先执行程序&#xff0c;在输入一个数 2.2.2 终端执行程序时同时输入一个预设变量 2.2.3 case带有按位或运算和通配符匹配 3.for语句 3.1for语句格式 3.2程序验…

图解模糊推理过程(超详细步骤)

我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数&#xff0c;下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数&#xff08;Π-shaped Membership Function&#xff09;的详细介绍及python示例”都有详细讲解&#xff1a;https://lzm07.b…

001-JMeter的安装与配置

1.前期准备 下载好JMeter : https://jmeter.apache.org/download_jmeter.cgi 下载好JDK : :Java Downloads | Oracle 中国 下载图中圈蓝的JMeter和JDK就行&#xff0c;让它边下载&#xff0c;我们边往下看 2.为什么要下载并安装JDK ? JMeter 是基于 Java 开发的工具&#…

英伟达有哪些支持AI绘画的 工程

英伟达在AI绘画领域布局广泛&#xff0c;其自研工具与第三方合作项目共同构建了完整的技术生态。以下是其核心支持AI绘画的工程及合作项目的详细介绍&#xff1a; 一、英伟达自研AI绘画工具 1. GauGAN系列 技术特点&#xff1a;基于生成对抗网络&#xff08;GAN&#xff09;&…

Netty源码—4.客户端接入流程二

大纲 1.关于Netty客户端连接接入问题整理 2.Reactor线程模型和服务端启动流程 3.Netty新连接接入的整体处理逻辑 4.新连接接入之检测新连接 5.新连接接入之创建NioSocketChannel 6.新连接接入之绑定NioEventLoop线程 7.新连接接入之注册Selector和注册读事件 8.注册Rea…

2025.3.17-2025.3.23学习周报

目录 摘要Abstract1 文献阅读1.1 动态图邻接矩阵1.2 总体框架1.2.1 GCAM1.2.2 输出块 1.3 实验分析 总结 摘要 在本周阅读的文献中&#xff0c;作者提出了一种名为TFM-GCAM的模型。TFM-GCAM模型的创新主要分为两部分&#xff0c;一部分是交通流量矩阵的设计&#xff0c;TFM-GC…

生活电子类常识——搭建openMauns工作流+搭建易犯错解析

前言 小白一句话生成一个网站&#xff1f;小白一句话生成一个游戏&#xff1f;小白一句话生成一个ppt?小白一句话生成一个视频&#xff1f; 可以 原理 总体的执行流程是 1&#xff0c;用户下达指令 2&#xff0c;大模型根据用户指令&#xff0c;分解指令任务为多个细分步骤…

深入解析 Uniswap:自动做市商模型的数学推导与智能合约架构

目录 1. 自动做市商&#xff08;AMM&#xff09;模型的数学推导1.1 恒定乘积公式推导1.2 价格影响与滑点 2. Uniswap 智能合约架构解析2.1 核心合约&#xff08;Core&#xff09;2.1.1 工厂合约&#xff08;Factory&#xff09;2.1.2 交易对合约&#xff08;Pair&#xff09; 2…

高频面试题(含笔试高频算法整理)基本总结回顾20

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…

生成模型速通(Diffusion,VAE,GAN)

基本概念 参考视频https://www.bilibili.com/video/BV1re4y1m7gb/?spm_id_from333.337.search-card.all.click&vd_sourcef04f16dd6fd058b8328c67a3e064abd5 生成模型其实是主要是依赖概率分布&#xff0c;对输入特征的概率密度函数建模 隐空间&#xff08;latent space)…

Android在kts中简单使用AIDL

Android在kts中简单使用AIDL AIDL相信做Android都有所了解&#xff0c;跨进程通信会经常使用&#xff0c;这里就不展开讲解原理跨进程通信的方式了&#xff0c;最近项目换成kts的方式&#xff0c;于是把aidl也换成了统一的方式&#xff0c;其中遇到了很多问题&#xff0c;这里…

学习本地部署DeepSeek的过程(基于ollama)

DeepSeek除了支持在线调用服务接口外&#xff0c;还支持本地部署后调用本地服务&#xff0c;这样的好处是不需要api key&#xff0c;且资源独占&#xff0c;还能训练个人知识库。本文学习并记录本地部署DeepSeek的过程。   参考文献3中列出了不同模型对于电脑硬件的要求&…

文献分享: ColXTR——将ColBERTv2的优化引入ColXTR

1. ColXTR \textbf{1. ColXTR} 1. ColXTR原理 1.1. ColBERTv2 \textbf{1.1. ColBERTv2} 1.1. ColBERTv2概述 1.1.1. \textbf{1.1.1. } 1.1.1. 训练优化 1️⃣难负样本生成 初筛&#xff1a;基于 BM-25 \text{BM-25} BM-25找到可能的负样本重排&#xff1a;使用 KL \text{KL} KL…

Altium Designer数模电学习笔记

模电 电容 **退耦&#xff1a;**利用通交阻直&#xff0c;将看似直流的信号中的交流成分滤除 &#xff08;一般用在给MPU供电&#xff0c;尽量小一些&#xff0c;10nf~100nf~1uf以下&#xff09; **滤波&#xff1a;**也可以理解为给电容充电&#xff0c;让电容在电平为低时…

从指令集鸿沟到硬件抽象:AI 如何重塑手机与电脑编程语言差异——PanLang 原型全栈设计方案与实验性探索1

AI 如何跨越指令集鸿沟&#xff1f;手机与电脑编程语言差异溯源与统一路径——PanLang 原型全栈设计方案与实验性探索1 文章目录 AI 如何跨越指令集鸿沟&#xff1f;手机与电脑编程语言差异溯源与统一路径——PanLang 原型全栈设计方案与实验性探索1前言一、手机与电脑编程语言…

python 实现一个简单的window 任务管理器

import tkinter as tk from tkinter import ttk import psutil# 运行此代码前&#xff0c;请确保已经安装了 psutil 库&#xff0c;可以使用 pip install psutil 进行安装。 # 由于获取进程信息可能会受到权限限制&#xff0c;某些进程的信息可能无法获取&#xff0c;代码中已经…