木骰

关于内建资源的冗余处理

主要参考了UWA上的这篇文章(与其说是参考,不如说是对它的实现):
https://blog.uwa4d.com/archives/1577.html
顶部编辑器工具菜单:

Alt text
1.CreateBuildInAssetsToEditor : 提取内置资源到编辑器目录Assets/BuildInAssets下,Shader部分需要自行去Unity官网下载对应版本。
2.CopyBuildInAssetsToEditor : 从Assets/../BuildInAssets目录,将之前提取出来的内置资源拷贝回Assets/BuildInAssets目录。
3.ClearLocalBuildInAssets : 删除Assets/BuildInAssets目录下的内建资源。
4.ReplaceBuildInAssetsReference :分析要打AB包的所有资源,将对内建资源的引用替换为提取到Assets/BuildAssets目录下资源的引用。
5.RevertBuildAssetsReference : 对进行替换过后的资源进行还原,并删除Assets/BuildInAssets下的资源。
在打包流程中(之前的自动打包工具),分析依赖之前,调用ReplaceBuildInAssetsReference,加入对内建资源依赖的替换,之后进入正常打包流程,打包结束后再调用RevertBuildInAssetsReference,将替换的资源还原,并删除本地内建资源,这样对正常开发流程完全无感知。

提取内建资源

Alt text
Assets/BuildInAssets目录结构,按资源类型划分。
该目录常驻在Assets下,每次删除的时候也只是删除每种类型目录下对应的资源内容,这样可以针对这些目录做一些打包配置,比如将 Image目录下的图片打到一个图集里, 将所有用到的Shader合并打到一个AB里等。
为了避免开发环境下编辑器里有两份相同的资源而变得混乱,内置资源被放置到Assets同级目录下,只在打包的时候才拷贝到编辑器下(原文是打成压缩包放在编辑器下,打包时才解压出来?)。
由于做增量打包的时候,一些资源会依据meta文件做差异比较,所以要保障meta文件不变,将内建资源提取出来后统一import一次,生成meta文件后再将BuildInAssets目录整个挪到Assets同级目录下。

提取内建资源时的一些注意点:

1.不能直接用AssetDatabase.CreateAsset来创建Load出来的内建资源,而应该先对load出来的资源进行一次克隆,调用Instantiate方法,再调用CreateAsset。
2.对于图片资源,由于内建资源的Texture关闭了Read/Write,所以不能用CreateAsset或EcodeToPng的方式直接创建,可以使用Graphics.Blit绘制到一张RT,再读取像素到一张新的Texture创建。

Alt text

进行依赖替换

Unity的资源文件,prefab,material,asset等,通过文本编辑器打开,都是YAML格式的内容,而其中对于其他资源的引用,都是通过以下格式的一段内容来描述:

m_Shader: {fileID: 207, guid: 0000000000000000f000000000000000, type: 0}

该语句表示了对一个Shader文件的引用。guid表示该资源文件的唯一ID,被记录在资源文件对应的meta文件中,fileID则表示该资源文件中,所引用对象的唯一ID(比如已个prefab文件中可能有多个组件对象),type则表示引用的资源类型,0代表内置资源,2代表复合类型的外部资源引用(material,prefab等),3代表基础类型的外部资源引用(图片,shader等)。
内置资源的guid只有 0000000000000000f000000000000000 和 0000000000000000e000000000000000 两种,基于此可以判断所引用的资源是否为内置资源。
Unity2019之后的版本开放了获取fileId和guid的接口,

AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out guid, out fileId);

基于此,就可以构建出一个内建资源与提取到本地的内建资源之间,fileId和guid的互相映射表,再使用正则对YAML进行批量检索和替换,就可以将对内建资源的引用全部替换为本地资源了。

替换引用时的一些注意点:

测试发现外部引用mesh资源也属于2类型,即复合类型,原文中说mesh是基础类型资源。
UnityEngine.Shader 类型的name获取到的是Shader文件中头部 Shader “XXXX” { 部分的内容,类似这样:

Shader "Hidden/InternalClear" {
CGINCLUDE

获取到的name就是 Hidden/InternalClear,这个name可能跟官网下载下来的Shader目录结构不一致,就无法通过这个name定位到对应的Shader文件。
解决这个问题可以在生成fileId和guid映射之前,先用正则捕获 Shader “XXXX” { 部分的名字,构造一张name与Shader路径的映射表。
对于一些字体文件,ttf,编辑器下的一些ttf文件的材质球和Shader可能是不允许修改的,类似这样:

Alt text
这个ttf文件直接是一个二进制文件,引用的材质球和贴图也直接包含在ttf文件下,并且编辑器下也不允许操作,这样就没法通过读取文本YAML的方式来修改它引用的Shader了。
测试发现对这种ttf字体,可以直接在代码里获取Font.material.shader并赋值,来修改所引用的Shader,就相当于对字体资源的引用替换特殊处理一下吧。

输出一下日志

Alt text
替换完成后输出一下替换和还原过的资源列表日志。

以上已整合到之前的打包工具中:
https://github.com/mutou1994/ABBuildSystem

— 于 共写了2476个字
— 文内使用到的标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*