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
  • 缓存数据的保存、读取和使用类同场景

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM框架的酒店预订系统

基于SSM框架的酒店预订系统的设计与实现 摘要 当今世界的互联网信息技术飞速发展&#xff0c;网络化的工作模式已经几乎覆盖到各个工作领域中的业务内&#xff0c;人们的日常生活也渐渐离不开互联网。因此&#xff0c;在当下全国各处的酒店都开始构建起了自己的网络预订系统。…

Win11文件右键菜单栏完整显示教程

近日公司电脑升级了win11&#xff0c;发现了一个小麻烦事&#xff0c;如下图&#xff1a; 当我想使用svn或git的时候必须要多点一下&#xff0c;这忍不了&#xff0c;无形之中加大了工作量&#xff01; 于是&#xff0c;菜单全显示教程如下&#xff1a; 第一步&#xff1a;管…

Java前端控制器模式

文章目录 以下是Java前端控制器模式的主要组成部分和工作原理&#xff1a;组件与角色&#xff1a;工作流程&#xff1a;应用场景与优势&#xff1a; Java Web应用程序示例 Java前端控制器模式是一种软件设计模式&#xff0c;它在构建基于Java的Web应用程序时特别有用&#xff0…

基于springboot实现在线拍卖系统项目【项目源码+论文说明】

基于springboot实现在线拍卖系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍…

2024/3/23打卡数组分割(第14届蓝桥杯)——二项式+快速幂

题目 思路 分析该题&#xff0c;要将集合 划分成两个子集 &#xff0c;且两个子集的和都是偶数。 可知&#xff1a;偶数 偶数 偶数&#xff1b;偶数 奇数 奇数&#xff1b;奇数 奇数 偶数&#xff1b; 分析可得&#xff1a;如果该集合的和为奇数&#xff0c;就不能分…

jQuery实现的会员中心安全修改表单特效代码

jQuery实现的会员中心安全修改表单特效代码是一款实现了可以修改登录密码&#xff0c;交易密码&#xff0c;手机号码&#xff0c;实名认证&#xff0c;电子邮箱&#xff0c;安全设置表单&#xff0c;会员表单等设置效果的代码 下载地址 https://www.qqmu.com/2635.html

卡行领航家用户端是怎么拼团怎么挣钱的?

#领航家代理政策/怎么代理/奖金制度/双2.0模式# 全国V&#xff1a;ok1234vip 领航家用户端&#xff1a;0.52费率 一次拼团0.44费率 两次拼团0.36费率 三次拼团0.2费率 ………… 十次拼团&#xff0c;客户每月挣20480 领航家代理端&#xff1a;无押激活返现高达166/台 分润万5-万…

智慧公厕的全域感知、全网协同、全业务融合和全场景智慧赋能

公共厕所是城市的重要组成部分&#xff0c;为市民提供基本的生活服务。然而&#xff0c;传统的公厕管理模式存在诸多问题&#xff0c;如排队等候时间长、卫生状况差、空气质量差等&#xff0c;严重影响市民的出行和生活质量。为了解决这些问题&#xff0c;智慧公厕应运而生&…

Spring IOC 容器的加载过程(bean 的创建过程)

Spring IOC 容器的加载过程&#xff08;bean 的创建过程&#xff09; 配置Bean 通过xml或者是Component Bean 等进行配置 解析Bean,得到BeanDefinition定义对象 通过 BeanDefintionReader 将 bean 进行解析&#xff0c;准备要创建的bean对象的定义对象BeanDefinition,存放到Be…

ATA-2048高压放大器在医疗中的作用是什么

高压放大器在医疗设备和医学应用中发挥着至关重要的作用。它们是一种专用的电子设备&#xff0c;用于放大医学图像和信号&#xff0c;以便医生能够更准确地诊断和治疗病患。下面西安安泰将详细介绍高压放大器的作用、原理和应用领域。 高压放大器是专门设计用于处理医学图像和信…

CrossOver虚拟机软件2024中文版最新功能介绍

CrossOver是一款由CodeWeavers公司开发的&#xff0c;运行在Mac和Linux操作系统下&#xff0c;能够模拟Windows系统应用运行环境的软件。它不需要用户单独安装Windows操作系统&#xff0c;就能让Windows平台上的应用程序在Mac和Linux上顺畅运行。CrossOver在技术上使用了Wine&a…

【数据存储】TIDB和MySQL的区别

1.TIDB和MySQL对比 对比内容MySQLTiDB架构设计一个传统的单机数据库系统&#xff0c;采用主从复制和分区表等方式来实现水平扩展一个分布式的 NewSQL 数据库&#xff0c;采用分布式存储和分布式事务等技术&#xff0c;支持水平扩展和高可用性事务支持 InnoDB 存储引擎来支持事…

一篇文章给你讲清楚正常卷积与深度可分离卷积

文章目录 正常卷积深度可分离卷积深度卷积逐点卷积 对比代码实现查看&#xff08;torch实现&#xff09;结果 正常卷积 也就是我们平常用的比较普遍的卷积&#xff1a; 它的参数量是&#xff1a;112&#xff0c;即&#xff1a; ( 卷积核大小&#xff09; ∗ 输入通道 ∗ 输出…

【JavaEE】_Spring MVC项目获取URL中的参数

目录 1. 单参数 2. 多参数 1. 单参数 .java文件如下&#xff1a; package com.example.demo.controller;import com.example.demo.Person; import org.springframework.web.bind.annotation.*;import java.util.Arrays; import java.util.List;RequestMapping("/Para&…

MFC 打开类向导中方法时提示对com组件的调用返回了错误 HRESULT E_FAIL

解决&#xff1a;头文件中要分类&#xff0c;把virtual和afx_msg等放在一起&#xff0c;不要交叉错开。 MFC&#xff08;Microsoft Foundation Class&#xff09;中的virtual关键字用于声明虚函数。虚函数是C中实现多态的一种机制&#xff0c;它允许派生类重新定义基类中的虚函…

FreeRtos学习笔记(12)systemView 分析任务调度情况

FreeRtos学习笔记&#xff08;12&#xff09;systemView 分析任务调度情况 使用stm32f429 freertosV10.5.1 systemView 3.5 keil AC5 systemView 移植 从官网下载 systemView 软件 将下面文件添加到工程中 freertos 修改 systemView 需要 FreeRTOSConfig.h 开启如下宏, …

UE小:CesiumForUnreal使用教程

联网模式&#xff08;需要翻墙&#xff09; 直接打开工程并点击Cesium插件图标然后点击connect to Cesium ion进行账号注册即可使用 见到如界面后点击Allow并返回UE编辑器&#xff08;如果无法打开认证界面请先访问https://ion.cesium.com/并且不要关闭&#xff0c;再次点击co…

Fendi Club啤酒:畅享时尚的味蕾之旅

在这个追求个性与品味的时代&#xff0c;Fendi Club啤酒以其时尚的魅力&#xff0c;领着时尚潮流与味蕾的完善结合。它不仅是一款啤酒&#xff0c;更是一种生活态度的象征&#xff0c;让我们一起踏上这场畅享时尚的味蕾之旅。 Fendi Club啤酒的特别之处在于它对品质的别致追求。…

SQL映射文件

一、SQL映射的xml文件 1.1 mapper元素 二、select 三、别名与Java映射 四、resultMap 啊

专题一_双指针(2)

目录 LCR 179. 查找总价格为目标值的两个商品 解析 题解 15. 三数之和 解析 题解 18. 四数之和 解析 题解 LCR 179. 查找总价格为目标值的两个商品 LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 解析 题解 class Solution { publi…