Unity构建详解(3)——SBP的依赖计算

【前置知识】

先要搞清楚Asset和Object的关系,可以简单理解为一个Asset对应多个Object。

unity自定义的Asset也要有一个存储的标准,其采用的是YAML,我们看到的所有Unity自定义的Asset格式,例如.prefab(预制体),.scene(场景文件),.asset(资源文件,例如ScriptableObject),.mat(材质球),.controller(动画状态机),还有图集等。

例如,prefab文件用YAML的格式记录了该Asset包含的Object,每个Object有一个FileID,用于区分Asset内的Object,每个Object中会记录自身的属性信息、包含的Type、引用的其他Object、引用的其他Asset、引用的其他Asset的Object等信息。

ObjectIdentifier是YAML中的Object的简要记录

可以建立这样一个层级一对多关系:Asset->Object->Type

【Native接口】

  • 获取一个Asset引用的其他Asset
    •  AssetDatabase.GetDependencies,可以获取直接或间接依赖, 这个操作比较耗时,可以优化Unity中资源依赖关系获取效率优化 - 知乎
  • 获取一个Asset引用的其他Asset的Hash值
    •  AssetDatabase.GetAssetDependencyHash
  • 获取一个Asset包含的ObjectIdentifier
    •  ContentBuildInterface.GetPlayerObjectIdentifiersInAsset
  • 获取一个或一系列Object引用的其他Object
    •  ContentBuildInterface.GetPlayerDependenciesForObjects
  • 获取一个Object中包含的Type
    •  ContentBuildInterface.GetTypesForObject
  • 获取一个Asset在目标平台上的Object,例如有些Object只在Editor上用,打包时要剔除
    •  ContentBuildInterface.GetPlayerAssetRepresentations
  • 计算Asset的使用情况,例如是否使用光照、雾效、阴影等,结果放在BuildUsageTagSet中
    •  ContentBuildInterface.CalculateBuildUsageTags

【什么是增量构建】

增量是缓存的一种方式,每次在已有缓存的基础上进行构建,就是增量构建。一般的缓存,例如对象池等,其数据还在内存中,增量时缓存数据要保存在磁盘中,构建时再加载到内存中。

【如何读代码】

我们看到的代码是完整的增量构建代码,但我们读代码时要分开来读。

构建是基础的,增量是新加的。要先看如何构建的,再看如何做增量的。

看构建时,要看:输入数据从哪来、输入数据如何使用(即输出数据从哪来)、输出数据是什么

看增量时,要看:缓存数据从哪来如何保存、缓存数据如何读取、缓存数据如何使用

总之要分开多个步骤跳着看,不要从方法的第一行顺着看到最后一行,很容易晕,而且也看不懂。

【CalculateSceneDependencyData】

输入数据从哪来

要计算场景的依赖,我们可以配置决定要计算哪些场景,配置好后会被保存到m_Content.Scenes 

 输入数据如何使用

这里就是如何计算得到场景的依赖数据,核心是调用

ContentBuildInterface.CalculatePlayerDependenciesForScene(scenePath, settings, usageTags, m_DependencyData.DependencyUsageCache);

返回值是SceneDependencyInfo结构体,其包含四个字段:

  • internal string m_Scene; 场景的名字
  • internal ObjectIdentifier[] m_ReferencedObjects;依赖的物体
  • internal Type[] m_IncludedTypes;包含的类型
  • internal BuildUsageTagGlobal m_GlobalUsage; 使用的类型

依赖分为递归和非递归两种,递归就是要依次获取所有的依赖,非递归只要获取直接依赖。

输出数据是什么
  • 得到所有Scene的依赖数据,放入到BuildDependencyData中,其是该Task的输出Data
    • m_DependencyData.SceneInfo.Add(asset, sceneInfo);
缓存数据如何获取

同一个对象,在不同的系统中会有不同的表示,也即会有不同的类,类中会有些相同的字段来表示同一个对象。

在构建中,场景的依赖数据放在SceneDependencyInfo中,每个Object对应一个 ObjectIdentifier

在增量中,场景的缓存数据放在CachedInfo中,每个Asset对应一个CacheEntry

缓存数据获取代码在if (uncachedInfo != null)中:

  • 通过AssetDatabase.GetDependencies获取某个场景依赖的Asset
  • 得到依赖中类型为prefab的CacheEntry
  • 计算所有CacheEntry的hash128,通过其了解场景的依赖是否发生变化
  • 计算得到该场景对应的CachedInfo
  • 保存所有场景的CachedInfo
缓存数据如何保存

保存代码为:m_Cache.SaveCachedData(uncachedInfo)

实现在 BuildCache.SaveCachedData中,用多线程进行保存的,用多线程是为了加速。

这里需要保存成文件,要有输入路径,也是可以配置的,默认是"Library/BuildCache"

缓存数据如何读取

读取代码为:m_Cache.LoadCachedData(entries, out cachedInfo);

要看懂数据如何读取/导入,要先看数据如何保存/导出

缓存数据如何使用

缓存数据必然包含输出数据,一般而言,就是直接拿来用,复杂些需要做个转换。这里直接拿来用即可。

使用缓存数据的核心问题是缓存的数据是不是最新的,有效的。因此,在使用缓存数据前,必须要有个方式判断缓存数据是否有效。

这里的方式是如果引用的Object的类型是Sprite,那么重新计算场景的依赖,得到新的ObjectIdentifier,对比前后的ObjectIdentifier以判断缓存数据是否有效。

【增量的数据结构】

CacheEntry:
  • public GUID Guid //该资源的GUID
  • public int Version //该资源的版本号,一般是1
  • public EntryType Type //该资源的类型,分为Asset\Data\File\ScriptType 四种,一般为Asset
  • public Hash128 Hash 
  • internal InclusionType Inclusion //显式还是隐式包含,明确配置的要收集的Asset是显式的,没有被配置但被配置的引用的Asset是隐式的
  • public string File //文件类型时文件的名字
  • public string ScriptType //脚本类型时脚本的名字
CachedInfo
  • public CacheEntry Asset 自身的CacheEntry
  • public CacheEntry[] Dependencies依赖的对应的CacheEntry
  • public object[] Data其他附加信息,这里用个Object[]数组来统合不同情况的数据,类似一个object类型的参数,很常见的处理方式。场景的Data为:
    • SceneDependencyInfo
    • BuildUsageTagSet
    • prefabDependency的Hash128
    • List<ObjectTypes> 每个Object所涉及的Type,即哪些脚本类

【CalculateAssetDependencyData】

构建时

将输入和输出数据又做了一层封装,封装成TaskInput和TaskOutput,感觉没有必要。

  • 输入数据就是要收集的所有Asset:m_Content.Assets
  • 计算该Asset的依赖数据
    •  var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset
    • var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects
  • 计算Object的依赖的Object数据
  • 计算对象构建使用情况
    • ContentBuildInterface.CalculateBuildUsageTags
  • 对于Sprite类型的资源,生成SpriteImporterData
  • 获取Asset的AssetRepresentations放入ExtendedAssetData,剔除Editor上的Object
    •  ContentBuildInterface.GetPlayerAssetRepresentations
  • 得到输出数据
    • 所有Asset的依赖数据,放入到BuildDependencyData中
      •  m_DependencyData.AssetInfo.Add(o.asset, o.assetInfo);
    • 所有Object的依赖数据,放入ObjectDependencyData中
      •  m_ObjectDependencyData.ObjectDependencyMap[objectDependencyInfo.Object] = objectDependencyInfo.Dependencies;
    • 所有Sprite的数据,放入BuildSpriteData中
      • m_SpriteData.ImporterData.Add(o.asset, o.spriteData)
    • 所有平台相关的数据,放入BuildExtendedAssetData中
      • m_ExtendedAssetData.ExtendedData.Add(o.asset, o.extendedData);
    • 所有的使用情况数据,放入BuildDependencyData中
      •   m_DependencyData.AssetUsage.Add(assetOutput.asset, assetOutput.usageTags);
增量时
  • 获取缓存数据GetCachedInfo,同样是CacheInfo这个数据结构
    •  public CacheEntry Asset //自身的CacheEntry
    • public CacheEntry[] Dependencies //依赖的Asset的CacheEntry,可以通过依赖的ObjectObjectIdentifier的GUID找到依赖的Asset
    • 自定义的数据,有些冗余
      •  BuildUsageTagSet
      • SpriteImporterData
      • ExtendedAssetData
      • List<ObjectTypes>
      • List<ObjectDependencyInfo>
      • AssetLoadInfo 类同SceneDependencyInfo
        •  internal GUID m_Asset; 自身的GUID
        • internal string m_Address 自身的路径
        • internal List<ObjectIdentifier> m_IncludedObjects; 包含的Object
        • internal List<ObjectIdentifier> m_ReferencedObjects; 引用的所有Object
  • 缓存数据的保存、读取和使用类同场景

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

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

相关文章

解决长尾问题,BEV-CLIP:自动驾驶中复杂场景的多模态BEV检索方法

解决长尾问题&#xff0c;BEV-CLIP&#xff1a;自动驾驶中复杂场景的多模态BEV检索方法 理想汽车的工作&#xff0c;原文&#xff0c;BEV-CLIP: Multi-modal BEV Retrieval Methodology for Complex Scene in Autonomous Driving 链接&#xff1a;https://arxiv.org/pdf/2401.…

【数据结构】快速排序(用递归)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解快速排序&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 基本思想二. 快速排序2.1 hoare版本2.2 挖坑法2.3 前后指针法2.4 快速排序优化三数取中法…

Python学习(一)

Python环境下载安装 安装略 验证安装结果与编写第一个Python程序

Vue 实现带拖动功能的时间轴

1.效果图 2. 当使用timeline-slider-vue组件时&#xff0c;你可以设置以下属性&#xff1a; date&#xff1a;用于设置时间轴滑块的初始日期&#xff0c;格式通常为 YYYY-MM-DD。 mask&#xff1a;一个布尔值&#xff0c;用于控制是否显示背景遮罩。 markDate&#xff1a;一…

需求:实现一个类似打印的效果(文字一个字一个字的输出)

实现效果&#xff1a; 需求&#xff1a;最近接到这么一个需求&#xff0c;ai机器人回复的问题&#xff0c;后端是通过websocket每隔一段事件返回数据&#xff0c;前端拿到数据后直接渲染&#xff0c;现在需要做到一个效果&#xff0c;后端返回的结果前端需要一个一个文字的输出…

MultiArch与Ubuntu/Debian 的交叉编译

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;基于ARM 的Linux系统的交叉编译 下一篇&#xff1a;MultiArch与Ubuntu/Debian 的交叉编译 警告&#xff1a; 本教程可能包含过时的信息。 什么是“MultiArch” OpenCV 可能…

【Canvas与艺术】暗蓝网格汽车速度仪表盘

【关键点】 采用线性渐变色&#xff0c;使上深下浅的圆有凹下效果&#xff0c;使上浅下深的圆有凸起效果&#xff0c;两者结合就有立体圆钮的感觉。 【图例】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type&quo…

php搭建websocket

1.项目终端执行命令&#xff1a;composer require topthink/think-worker 2.0.x 2.config多出三个配置文件&#xff1a; 3.当使用php think worker:gateway命令时&#xff0c;提示不支持Windows。 4.打包项目为zip格式 5.打包数据库 6.阿里云创建记录 7.宝塔面板新增站点…

win10如何录制视频?解锁屏幕录制新姿势!

在Windows 10操作系统中&#xff0c;视频录制已经成为一项非常实用的功能。无论是进行在线教育、游戏直播&#xff0c;还是制作教学视频、会议记录&#xff0c;一款易于使用且功能强大的录屏软件都是必不可少的。在本文中&#xff0c;我们将向您介绍win10如何录制视频的三种方法…

一枝独秀,基于区块链共益型短视频平台享视,真的能抗衡各大短视频平台吗

早在2006年&#xff0c;全球非营利性组织共益实验室(B Lab)就提出了共益企业(B Corp)的概念&#xff0c;致力于推动商业向善。 但时至今日&#xff0c;共益企业发展仍处初级阶段&#xff0c;而且只强调要对社区、员工、环境、供应商、消费者等利益相关者负责&#xff0c;认定标…

【协议-HTTPS】

https https是在http协议的基础上&#xff0c;添加了SSL/TLS握手以及数据加密传输&#xff0c;也属于应用层协议。 httpshttp加密认证完整性保护 https交互图&#xff1a; HTTPS的整体过程分为证书验证和数据传输阶段&#xff1a; ① 证书验证阶段 浏览器发起 HTTPS 请求 服务…

电脑不能读取移动硬盘,但是可以读取U盘解决方法

找到此电脑 右键设备管理器&#xff0c;找到其中的通用串行总线控制器。 注意&#xff0c;凡是插入到电脑当中不能读取的U盘或者移动硬盘&#xff0c;都会在通用串行总线控制器当中显示为USB大容量存储设备 鼠标选中“USB大容量存储设备”&#xff0c;右键卸载它。此时&#x…

【算法每日一练]-动态规划(保姆级教程 篇17 状态压缩)#POJ1185:炮兵阵地 #互不侵犯

目录 今日知识点&#xff1a; 把状态压缩成j,dp每行i的布置状态&#xff0c;从i-1和i-2行进行不断转移 把状态压缩成j,dp每行i的布置状态&#xff0c;从i-1行进行状态匹配&#xff0c;然后枚举国王数转移 POJ1185&#xff1a;炮兵阵地 思路&#xff1a; 题目&#xff1a;互…

Verilog刷题笔记44

题目&#xff1a;Consider the n-bit shift register circuit shown below: 解题&#xff1a; module top_module (input clk,input w, R, E, L,output Q );always(posedge clk)beginif(L1)Q<R;elseQ<(E1)?w:Q;endendmodule结果正确&#xff1a; 注意点&#xff1a; …

吴恩达2022机器学习专项课程(一) 3.6 可视化样例

问题预览 1.本节课主要讲的是什么&#xff1f; 2.不同的w和b&#xff0c;如何影响线性回归和等高线图&#xff1f; 3.一般用哪种方式&#xff0c;可以找到最佳的w和b&#xff1f; 解读 1.课程内容 设置不同的w和b&#xff0c;观察模型拟合数据&#xff0c;成本函数J的等高线…

安卓studio连接手机之后,一两秒之后就自动断开了。问题解决。

太坑了&#xff0c;安卓studio链接手机之后。几秒之后就断开了。我以为是adb的问题&#xff0c;就重新安装了一下adb。并且在环境变量中配置了Path的路径。然而并没有什么用啊。 经过排查原来是数据心虚了。线的接触不良。导致你刚接通的瞬间有相对较强的电流是因为有瞬间高电压…

【ArcGIS微课1000例】0106:ArcGIS制作风向频率(风速)玫瑰图

文章目录 一、效果预览二、加载数据三、创建图表四、图表修饰五、保存图片一、效果预览 在ArcGIS制作的风向频率玫瑰图最终效果如下所示: 二、加载数据 加载配套实验数据包中0106.rar中的excel数据,然后右键→打开。 三、创建图表 1. 创建图表。右击打开属性表,选择表选项…

Mac电脑高清媒体播放器:Movist Pro for mac下载

Movist Pro for mac是一款专为Mac操作系统设计的高清媒体播放器&#xff0c;支持多种常见的媒体格式&#xff0c;包括MKV、AVI、MP4等&#xff0c;能够流畅播放高清视频和音频文件。Movist Pro具有强大的解码能力和优化的渲染引擎&#xff0c;让您享受到更清晰、更流畅的观影体…

蓝桥杯第十五届抱佛脚(二)竞赛中的数据结构

蓝桥杯第十五届抱佛脚&#xff08;二&#xff09;内置数据结构 文章目录 蓝桥杯第十五届抱佛脚&#xff08;二&#xff09;内置数据结构在竞赛中常见的数据结构数组(Array)链表(Linked List)栈(Stack)队列(Queue)树(Tree)映射(Map) 内置数据结构的快速使用迭代器&#xff08;It…

(一)基于IDEA的JAVA基础7

关系运算符 运算符 含义 范例 结果 等于 12 false &#xff01; 不等于 1&#xff01;2 true > 大于 1>2 false < 小于 …