EntityComponentSystemSamples 实战:在 Entities Graphics 中正确使用多子网格(Submesh)与多材质烘焙
【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples
本文是 EntityComponentSystemSamples 仓库中 HDRP Samples 项目的技术指南,围绕 Submesh 示例场景 展开。该场景演示了 Entities Graphics 如何烘焙带多个 sub-mesh 的 Mesh,以及"一个 Entity 只能绑定一个 Material"这一核心约束下,多材质 GameObject 会被拆分为多个 Entity 的底层行为。读完本文,你将理解 sub-mesh 与材质的对应关系、烘焙拆分的触发条件,并能通过 Entities Hierarchy 窗口亲手验证这一拆分过程,为后续处理复杂网格资源打下基础。
一、示例场景概述
在 HDRP Samples 项目中,Submesh场景位于 6. Misc 目录,是官方用于演示Entities Graphics 多子网格支持的样例。项目主 README 对它的定位是:"Demonstrates using a Mesh with multiple sub-meshes with Entities Graphics"(GraphicsSamples/HDRPSamples/README.md)。
整个场景的构成非常精简:
- 一个"空壳"主场景 Submesh.unity,只包含 Main Camera、Directional Light、一个地面 Plane 和一个带有
AutoLoadScene: 1的 SubScene 组件; - 一个 SubScene.unity,内部仅有一个名为
Cubes的 authoring GameObject。
也就是说,演示逻辑全部收敛在 SubScene 的单个 GameObject 上——这正是观察"多材质被拆分为多 Entity"的最干净样本。
二、场景里到底有什么:一个 Mesh、三个 Sub-Mesh、三个材质
2.1 Mesh 资源的子网格结构
SubScene 中的CubesGameObject 通过MeshFilter引用了 Cubes.asset 这个 Mesh 资源。打开该资产的 YAML 序列化文件,可以看到m_SubMeshes数组中定义了三个子网格:
| 子网格 | firstByte | indexCount | vertexCount | 包围盒中心 (x) | 对应立方体 |
|---|---|---|---|---|---|
| SubMesh 0 | 0 | 36 | 24 | 0 | 第 1 个立方体 |
| SubMesh 1 | 72 | 36 | 24 | 3.25 | 第 2 个立方体 |
| SubMesh 2 | 144 | 36 | 24 | 1.62 | 第 3 个立方体 |
每个子网格indexCount: 36(即 12 个三角形),vertexCount: 24,正好是一个立方体的标准面数/顶点数;三个子网格共享同一个顶点缓冲区(m_VertexCount: 72),通过firstByte区分各自的索引段。从顶点数据(_typelessdata中的坐标分量)可以看到,三个立方体被放置在 x 轴上的不同位置,最终 Mesh 的整体包围盒为m_Center: {x: 1.625, y: 0, z: 0}、m_Extent: {x: 2.125, y: 0.5, z: 0.5}。
2.2 材质的挂接方式
Cubes的MeshRenderer组件上挂了一个长度为 3 的材质数组,分别指向 SceneAssets 下的三个 HDRP Lit 材质(通过.meta中的 guid 可确认对应关系):
Red.mat(guid45b59214118ecdb448f7015259ff6d38)——_BaseColor为{r: 1, g: 0, b: 0}Green.mat(guid02e0265043393054c90dd96499c50df8)——绿色Blue.mat(guidc45ea55d5584dec4d917f1447b823b5d)——蓝色
材质本身是标准的 HDRP Lit 材质(m_Shader指向 HDRP Lit shader,m_SurfaceType: 0为 Opaque,m_CustomRenderQueue: 2225),未使用任何纹理,仅通过_BaseColor区分颜色,目的就是让拆分结果在 Entities Hierarchy 中一目了然。
在传统 GameObject 渲染管线中,MeshRenderer会把第 N 个材质按顺序应用到第 N 个子网格上,即"红、绿、蓝"三色立方体由一个 GameObject 一次绘制完成。
三、核心机制:为什么一个 GameObject 会被烘焙成多个 Entity
3.1 Entities Graphics 的"一 Entity 一材质"约束
这是本示例要演示的最关键原理:Entities 只支持一个 Entity 绑定一个 Material(原文:"Entities support only a single Material per Entity")。
Entities Graphics 的数据组织以RenderMesh组件为核心,一个 Entity 对应一份 Mesh + Material 的组合。因此当烘焙器(Baker)遇到"一个 Mesh 带多个子网格 + 多个材质"的 authoring GameObject 时,无法用一个 Entity 完整表达,只能执行拆分策略:
把该 GameObject 按"材质"维度拆分为若干 Entity,每个 Entity 持有原始 Mesh 的一个子网格,并绑定对应的那个 Material。
场景中的Cubes有 3 个子网格、3 个材质,于是被烘焙成3 个独立的 Entity,分别对应红色立方体、绿色立方体、蓝色立方体。每个 Entity 的 Mesh 都是原始CubesMesh 的其中一个 sub-mesh,材质则各取其一。
3.2 与烘焙管线的对应关系
这一行为发生在 SubScene 的 baking 阶段。从场景配置可以验证:
- Submesh.unity 中的 SubScene 组件引用 SubScene.unity;
- SubScene 内的
Cubes在烘焙时由MeshRenderer组件触发生成RenderMesh相关组件; - 多材质导致拆分后,运行时 / Entities Hierarchy 中呈现为多个 Entity,但它们共享同一个网格顶点缓冲与索引缓冲(体现在
Cubes.asset中三份子网格共享m_VertexData),只是绘制时各自取用对应的子网格索引区间和材质。
换句话说,拆分是"逻辑层"的拆分,GPU 侧的顶点数据仍然是一份,这保证了拆分的开销很小。
四、动手验证:在 Entities Hierarchy 中观察拆分结果
4.1 操作步骤
原文档给出了完整的验证流程,逐条对照执行即可:
- 确保 Hierarchy 中 SubScene 处于关闭状态——SubScene 未打开时,其中的内容以 Entity 形式存在于实体世界中,而不是作为 GameObject 暴露在普通场景层级中;
- 打开菜单Window > Entities > Hierarchy,调出实体层级窗口;
- 在窗口中定位到该 SubScene(导航到 SubScene 对应节点);
- 展开其下"带层级结构的 Entity"(即烘焙自
Cubes的那组 Entity); - 观察:存在三个 Entity,它们全部由同一个 authoring GameObject 烘焙而来。
4.2 预期看到的验证结果
展开后,你会看到类似下面的结构(以官方描述为准,具体节点命名以打开场景时为准):
- 一个父级 Entity(对应烘焙后的整体,通常携带 Transform 等信息);
- 其下 3 个子 Entity:
- Entity A —— 红色立方体(Cubes 子网格 0 + Red.mat)
- Entity B —— 绿色立方体(Cubes 子网格 1 + Green.mat)
- Entity C —— 蓝色立方体(Cubes 子网格 2 + Blue.mat)
这 3 个 Entity 的 Mesh 引用都指向同一个CubesMesh 资源,区别在于子网格索引与材质引用不同。这就是"多材质 GameObject → 多 Entity"的最直观证据。
五、延伸思考:多子网格资源在实际项目中的处理建议
5.1 何时该用多子网格
Unity 的 Mesh 支持"一个资源含多个子网格",常见于以下场景:
- 共享顶点数据的组合体:多个部件(如汽车车身、车轮、车窗)合并成一个 Mesh 资源,但需要不同材质;
- 美术 DCC 工具导出的合并网格:模型在建模软件中合并导出后自带多个 material slot;
- LOD / 部件分离:运行时按需绘制部分子网格。
在上述场景中引入 Entities Graphics 时,本示例揭示的拆分行为会自动生效:无需手动改造美术资源,烘焙器会自动按材质把资源拆成多个 Entity。
5.2 从拆分机制出发的实用建议
- 性能权衡:拆分会增加 Entity 数量与 Draw Call 数量(一个子网格+一个材质 = 一次绘制)。如果某些子网格使用同一材质,可以考虑在 DCC 工具中合并,减少拆分后的 Entity 数量;
- 材质一致性:由于拆分粒度是"按材质",保证同一视觉单元的子网格尽量使用同一材质,可以让烘焙结果更紧凑;
- 运行时修改:拆出来的每个 Entity 拥有独立的
RenderMesh数据,运行时可按 Entity 单独替换材质或隐藏/显示,这比在传统管线中切换整个 Renderer 的材质数组更符合 ECS 的数据驱动风格(仓库中 MaterialMeshChange 场景对此有更专门的演示); - URP 同样适用:本示例在 URPSamples 项目中也有对应副本,说明该拆分行为是 Entities Graphics 的通用规则,与渲染管线(HDRP/URP)无关。
六、相关资源索引
- 示例 README:GraphicsSamples/HDRPSamples/Assets/SampleScenes/6. Misc/Submesh/README.md
- 运行效果截图:GraphicsSamples/HDRPSamples/READMEimages/Submesh.png
- 主场景:Submesh.unity(含 SubScene 组件与基础灯光/相机)
- SubScene 内容:Subscenes/SubScene.unity(含唯一的
Cubesauthoring GameObject) - 多子网格 Mesh 资源:SceneAssets/Cubes.asset(3 个子网格,共享 72 个顶点)
- 三个材质:Red.mat、Green.mat、Blue.mat
- HDRP 项目样例总览:GraphicsSamples/HDRPSamples/README.md
- URP 同款示例:GraphicsSamples/URPSamples/Assets/SampleScenes/6. Misc/Submesh/README.md
七、小结
通过本示例可以确认 Entities Graphics 对多子网格 Mesh 的处理规则:一个 Entity 只能持有一种材质,因此带多材质子网格的 authoring GameObject 会在烘焙时被自动拆分为多个 Entity,每个 Entity 共享网格数据、各自绑定一个子网格和一个材质。在实际项目中,理解这一机制有助于预估 Entity 数量与 Draw Call 开销,并为美术资源合批策略提供决策依据。如果你需要进一步探索 Entities Graphics 的其他能力,仓库中的 MaterialMeshChange(运行时换材质/网格)与 RenderMeshUtilityExample(运行时创建渲染实体)场景是很好的下一站。
【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考