在 Unity 中导入模型材质球的最优雅姿势
🥦Model Importer 前言
对于项目中模型的材质球导入问题一直没有明确的规范, 导致这块美术资源的处理要么依赖出问题, 分包出问题, 资源加载卡顿, 要么产生的额外材质球导致版本管理异常, 到处充斥着 Unity 拉的屎, 这里一坨, 那里一坨, 对于我这种强迫症晚期患者而言, 每每看见一坨坨的屎, 上班的心情都没有了~
想起来自己曾经处理过这个问题, 但是当时的思路还是模模糊糊的, 处于一种总感觉哪里有问题却又说不上来的状态, 于是趁最近几天的空闲时间, 再次把这个问题捡起来, 彻底把坑填上!
先来看一下官方对模型导入材质球的说明: 跳转官方手册 Materials tab
🎈Material Tab 解析
先来彻底解析一下 Model Importer 的 Material 页面
这个页面就是控制 Unity 如何生成材质球的, 生成材质球的模式有 3 种: None
Standard (Legacy)
Import via MaterialDescription
下面来逐一说明
None
此模式下 Unity 将不参考任何模型数据, 而是直接引用 Unity 标准材质球, 原文是 "Unity's default diffuse Material"
Standard (Legacy)
此模式下 Unity 将使用一组默认规则生成材质球, 即规则固定, 不支持自定义, 同时标准模式也不支持复杂的材质球
比如 Arnold Material
Physical Material
HDRP Material
等
Import via MaterialDescription
此模式下 Unity 将使用 FBX 文件中嵌入的材质描述来生成材质, 相比标准模式, 此模式可以提供更准确的结果并支持更广泛的材质类型
🍸三种模式的总结
None
模式下会引用标准材质球, 并且无法移除, 因此不满足要求
Standard (Legacy)
模式下会按默认规则生成材质球, 但是可以移除, 因此可以使用此模式
Import via MaterialDescription
模式下会按材质描述生成材质球, 也可以移除, 因此也可以使用此模式
但是考虑到项目中并不使用 Unity 生成的材质球, 因此后两种模式都可以, 反正都是要移除的, 这里选择 Standard (Legacy)
再次说明, 因为并不需要使用 Unity 生成的材质球, 所以后两种模式都满足目前的要求, 都可以选择, 没有区别
🍀Standard (Legacy)
下面来详细说明一下 Standard (Legacy)
模式
- sRGB Albedo Colors
此选项控制使用伽马空间还是线性空间
说实话我并没有图形学相关知识, 我感觉这个选项技美人员肯定知道怎么设置, 交给专业人士了! 我们来看其他选项
- Location
重点来了 Location
选项, 这个选项用来控制 Unity 生成材质球的位置, 有 2 种选择
Use External Materials (Legacy)
和 Use Embedded Materials
我来逐个说明
🍇Use External Materials (Legacy)
这个选项下, Unity 会尝试查找已有的材质球资源, 查找时按照 Naming
和 Search
配置的查找方式进行查找 (查找方式的配置在本文最后)
那如果找不到会怎么样呢? 会 使用默认规则新建材质球资源并放置于同级的 Materials 文件夹中
上图中可以看到, 模型 Model Demo 同级目录中有一个 Materials 文件夹, 里面存放的就是 Unity 在标准模式下生成的材质球
🍉 External 模式总结
优先尝试搜寻外部材质球, 搜寻不到则按默认规则新建材质球
只有当模型和材质球具有强制要求的命名规则, 并且强绑定, 材质球不会复用的情况下才推荐 Use External Materials (Legacy) 设置
否则一旦 Unity 找不到对应的材质球便会新建 Materials 文件夹以及对应的材质球资源, 但是没有哪个项目会使用 Unity 生成的默认材质球的, 这部分默认材质球很显然是多余的资源!
因此不推荐!
接下来看另一个选项
🍒Use Embedded Materials
这个选项下, Unity 会直接使用默认规则新建材质球资源
但是和上一个选项不同的是不再放置于同级的 Materials 文件夹中, 而是直接作为模型的 SubAsset
从上图中可以很明显地看到生成了 01 - Default
02 - Default
03 - Default
三个材质球, 并且是作为模型内嵌资源的形式
但是作为内嵌资源的方式有很大的弊端, 那就是无法修改材质球的参数, 为了解决这个问题, Unity 提供了 资源导出
功能
资源导出功能
- Extract Materials
提取 Unity 使用默认规则新建的作为模型 SubAsset 资源的材质球资源到指定的目录中
- Extract Textures
提取 Unity 使用默认规则新建的作为模型 SubAsset 资源的贴图资源到指定的目录中
使用上述两按钮便可以导出 Unity 创建的材质球和贴图, 并且会将导出信息记录在 meta 文件的 externalObjects
字段中
导出时无法指定某一个材质球或纹理单独导出, 只能导出全部的材质球或者全部的纹理
每一条导出信息都由以下信息构成, 其中最关键的就是 name
信息, 只有名称和模型中记录的名称完全匹配的信息才视为一条正确的导出信息
1 | - first: |
但是资源导出功能也仅仅是将资源导出而已, 使用的还是 Unity 按照默认规则生成的资源, 并不是我们自己的资源, 于是还有一个功能 资源重映射
功能
资源重映射功能
Remapped Materials
同样使用 Naming
和 Search
配置的查找规则尝试查找重映射材质球
1 | - first: |
上面是一条合法的导出信息, 重映射功能修改的就是其中的 guid
字段信息
因此 资源重映射
功能是以 资源导出
功能为基础的, 如果此时 meta 文件中没有任何导出信息, 执行重映射时便会自动新建对应材质球的导出信息, 相当于将指定的一个材质球执行了导出操作, 其余没有创建导出信息的依旧会以内嵌资源 (SubAsset) 的形式存在于模型资源中
🍍Embedded 模式总结
简单概括: 不存在导出信息时以内嵌资源的形式创建材质球, 存在导出信息时引用导出信息中的资源
此模式在存在导出信息时会直接引用导出信息中的资源, 因此自定义程度极高, 强烈推荐此模式!
但是要注意, 在没有导出信息的情况下, Unity 依旧会创建材质球, 虽然是以内嵌资源的形式, 但这依然不是我们想要的, 所以切记要设置导出信息才行!
强烈推荐!
🥒如何批量设置导出信息
本文最后会贴出完整代码, 这里就只说一下思路
- 将模型导入设置修改为 Standard + Embedded, 并重新序列化 meta 文件
这是为了统一导入设置, 同时规范 meta 文件的格式, 为后面文本处理做准备
- 使用逐行扫描的方式删除 " externalObjects:" 到 " materials:" 的全部 Remap 信息
这里为什么不使用 Unity 自带的 RemoveRemap
呢? 因为模型中很可能会存在非法的 Remap 信息, 使用 RemoveRemap
根本无法移除这部分信息
另外模型的 meta 文件结构固定且内容不多, 而且前面我们已经重新序列化了 meta 文件, 保证了 meta 文件格式的正确性, 因此直接逐行分析即可, 同时多线程进行优化
- 添加空的 Remap 信息
Remap 信息清空后, 只要添加空的 Remap 信息就可以实现既不生成额外资源, 又不会引用到外部资源的效果!
至此结束, 具体代码可查看本文最后! 最后实现的效果如下, 可以看到正确生成了导出信息并且没有引用额外的资源!
「算是某种意义上的卡 Bug?什么叫 Bug?!这叫机制!」
1 | - first: |
🍑总结
模式 | 描述 | 是否推荐 |
---|---|---|
None | 直接引用 Unity 默认材质球,无法移除 | ❌ 不推荐 |
Standard (Legacy) | 按默认规则生成材质球,可移除 | ✅ 可选 |
Import via MaterialDescription | 按材质描述生成材质球,可移除 | ✅ 可选 |
Use External Materials (Legacy) | 优先查找外部材质球,找不到则新建材质球资源 | ❌ 不推荐 |
Use Embedded Materials | 生成材质球为 SubAsset,可配合导出和重映射功能 | ✅ 强烈推荐 |
Extract Materials | 提取 Unity 生成的材质球资源 | |
Extract Textures | 提取 Unity 生成的纹理资源 | |
Remapped Materials | 通过导出信息替换默认材质 |
🌳附录一:查找规则的配置
Naming
用于控制搜索时的名称规则
By Base Texture Name
使用材质关联的主纹理名称作为线索进行查找
Fome Model's Material
直接使用模型文件中定义的材质名称作为线索进行查找
Model Name + Model's Material
组合模型文件名和模型文件中定义的材质名作为线索进行查找
Search
用于控制搜索的位置
Local Materials Folder
仅在模型文件同级目录的 Materials 文件夹中搜索
Recursive Up
从模型文件所在目录开始向上逐级递归搜索
Project Wide
在整个项目范围内搜索
🍈附录二:为什么 Extract Materials 按钮, Extract Textures 按钮是置灰的 ?
这两个按钮在两种情况下是置灰的
模型内部没有材质球和贴图时
meta 文件中已经记录了全部资源的导出信息时
第一种情况很好理解, 关键是第二种情况, 假设 Unity 检测到模型中有 3 张纹理, 2 个材质球
tex_1
tex_2
tex_3
mat_1
mat_2
而目前 meta 中已经记录了 2 张纹理和 2 个材质球的导出信息
tex_1
tex_2
mat_1
mat_2
则导出贴图按钮就是可用的, 导出材质球按钮就是置灰的
🥕附录三:设置模型导出信息的完整代码
1 | /// <summary> |