EntityComponentSystemSamples HDRP 项目解析:Entities Graphics 特性示例场景全景指南
【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples
本项目(EntityComponentSystemSamples 仓库中的GraphicsSamples/HDRPSamples子工程)以 Unity DOTS 生态的com.unity.entities.graphics包(1.4.16 版)与 HDRP 渲染管线(17.2.0 版)为核心,通过 20 余个特性示例场景,系统演示了 Entities 在 HDRP 下的渲染能力:从光照烘焙、材质逐实例覆盖、运行时实体创建,到网格形变、LOD、运动模糊与透明排序。读完本文,你将掌握每个示例场景的玩法、操作步骤,以及其背后的 ECS 渲染机制与关键源码实现路径,可直接在本仓库中逐一打开场景进行验证与二次开发。
项目概览与核心渲染机制
Entities Graphics 与 SubScene 的渲染模型
HDRPSamples 是面向HDRP Entities Graphics的特性示例工程。其核心机制在于:当存在对应实体(Entity)时,Unity 用 Entities Graphics 渲染该 GameObject;当实体不存在时,则不使用 Entities Graphics 渲染。对于放在 SubScene 中的 GameObject,这一行为意味着 Unity在编辑模式(Edit Mode)、播放模式(Play Mode)以及打包后的 Player 中始终以 Entities Graphics 渲染它们——这正是 DOTS 烘焙(Baking)带来的运行路径统一。
特性示例场景全部位于 GraphicsSamples/HDRPSamples/Assets/SampleScenes 目录,按主题划分为0. Base至6. Misc七个分类目录,绝大多数场景都把演示用的 GameObject 放入 SubScene 中烘焙为实体。工程运行环境可从仓库确认:Unity 编辑器版本为6000.2.10f1(见 ProjectVersion.txt),依赖com.unity.entities.graphics: 1.4.16与com.unity.render-pipelines.high-definition: 17.2.0(见 Packages/manifest.json)。
场景总览表
主 README(GraphicsSamples/HDRPSamples/README.md)以表格形式给出了全部特性场景的一览,以下完整继承该场景清单:
| 场景 | 说明 |
|---|---|
| AmbientAndBlendProbes | 演示如何使用光照探针(light probes) |
| Lightmaps | 演示 Entities 的光照贴图支持 |
| Lightprobes | 演示 Entities 的光照探针支持 |
| BuiltInMaterialSHProperties | 演示覆盖内置材质的 SH 属性值 |
| HDRPLitProperties | 演示不同 HDRP Lit 材质属性在实体上的覆盖 |
| HDRPShaders | 演示 HDRP Lit、LitTessellation、Unlit、LayeredLit、LayeredLitTessellation 着色器的材质属性覆盖 |
| MaterialOverridesSample | 演示无需写代码即可覆盖材质属性 |
| ShaderGraphProperties | 演示 Shader Graph 着色器的材质属性覆盖 |
| HybridEntitiesConversion | 演示可放入 SubScene 的图形相关伴随组件(companion components) |
| TriggerParticles | 演示如何从 ECS System 播放 VFX |
| EntityCreation | 演示如何在运行时高效创建由 Entities Graphics 渲染的实体 |
| MaterialMeshChange | 演示在运行时更换实体上的材质与网格 |
| RenderMeshUtilityExample | 演示RenderMeshUtility.AddComponentsAPI |
| MeshDeformations | 演示 BlendShape 与 SkinWeight 实体 |
| SkinnedCharacter | 演示 SkinnedMeshRenderer 实体 |
| DisabledEntities | 演示被禁用的实体 |
| LODs | 演示 Entities Graphics 中的 LOD |
| MatrixPrevious | 演示移动实体与 HDRP 运动矢量(Motion Vectors)支持 |
| Submesh | 演示带多个子网格(sub-mesh)的 Mesh 配合 Entities Graphics 使用 |
| TransparencyOrdering | 演示透明实体的排序 |
运行方式:Base 场景切换器
0. Base目录下的 Base.unity 是导航入口场景,运行后可在播放模式下切换到工程内任意场景(见 0. Base/README.md)。切换逻辑由 SimpleSceneSwitch.cs 实现:界面右下角提供 Prev / Next 按钮(或按 Fire1 / Fire2 键)在 Build Settings 中的场景间轮转;切换时它会通过EntityManager.GetAllEntities()清理运行时生成的实体,但会跳过 SubScene、SceneSection 与场景流式单例等系统实体,避免误删引发报错。单独体验某个示例时,也可直接在 Project 窗口中打开对应分类目录下的场景文件并进入 Play 模式。
光照与烘焙示例(1. Lighting)
AmbientAndBlendProbes:SubScene 中的环境光与混合探针
该场景(AmbientAndBlendProbes.unity)演示 SubScene 中环境光与混合探针(blend probes)的工作方式:场景中有 2 个 SphereAmbient 与 2 个 SphereBlend 对象,其中 2 个在 SubScene 外、2 个在 SubScene 内,且两侧使用完全相同的MeshRenderer.Probes.LightProbes配置。操作要点(见 AmbientAndBlendProbes/README.md):在 Hierarchy 中选中任一球体,在 Inspector 的Mesh Renderer - Probes - Light Probes下观察其设置是 Off 还是 Blend Probes。该场景用于验证:烘焙进 Entities 后,光照探针的混合策略依然按原 MeshRenderer 配置生效。需要特别注意的是,SubScene 内的光照探针数据依赖探针锚点与包围体的放置,若自行修改场景需保持探针覆盖到实体区域。
Lightmaps:Entities 的光照贴图支持
Lightmaps.unity 场景(Lightmaps/README.md)由使用不同光照着色器(lit shaders)的球体组成,并启用烘焙全局光照(baked GI)。使用步骤:
- 在 Hierarchy 选中 Subscene,在 Inspector 点击Open打开;
- 进入Window > Rendering > Lighting;
- 在 Scene 选项卡配置光照贴图设置,点击Generate Lighting烘焙;
- 保存场景与 SubScene,然后关闭 SubScene。
烘焙结果以光照贴图(lightmap)形式供 Entities Graphics 读取,实体的 UV 需与烘焙贴图对应,否则会出现漏光或错位。
Lightprobes:实体上的光照探针
Lightprobes.unity 场景(Lightprobes/README.md)用光照探针为不同光照着色器的球体打光。操作上需要注意的关键差异:SubScene 内的灯光标记为 Static,而球体不标记 Static。步骤:
- 打开 SubScene;
- 确认灯为 Static、球体非 Static;
- 进入Window > Rendering > Lighting;
- 在 Scene 选项卡确保开启Baked Global Illumination,配置好光照贴图设置后点击Generate Lighting;
- 保存并关闭 SubScene。
这种 Static 组合让探针烘焙为静态数据、实体本身保持动态变换,是光照探针 + ECS 实体的标准配合方式。
材质属性覆盖示例(2. MaterialProperties)
材质属性覆盖(material property override)是 Entities Graphics 实现逐实例(per-instance)材质差异的核心能力:不必复制材质,而是通过带[MaterialProperty]特性的 ECS 组件把数值写入渲染批量。仓库中的生成代码可直接印证这一点,例如 HDRPMyColorVector4OverrideOverrideGenerated.cs:
namespace Unity.Rendering { [MaterialProperty("_HDRPMyColor")] struct HDRPMyColorVector4Override : IComponentData { public float4 Value; } }即:一个带[MaterialProperty("着色器属性名")]的IComponentData结构体,其字段值会被注入到对应着色器属性中,实现同材质不同实例显示不同颜色/金属度/光滑度。
HDRPLitProperties:覆盖 HDRP Lit 核心属性
HDRPLitProperties.unity(HDRPLitProperties/README.md)中的球体使用 HDRP Lit 着色器并位于 SubScene 内,挂载在球体 MeshRenderer 上的材质覆盖 Authoring 组件会覆盖其颜色(Color)、光滑度(Smoothness)与金属度(Metallic)。若需覆盖其他 HDRP 材质属性,可以在 Inspector 中继续添加其他 HDRP Material Property Authoring 组件(如 Base Color、Emissive Color、Normal、Ambient Occlusion 等),每个组件烘焙后都会生成对应的[MaterialProperty]ECS 组件。
HDRPShaders:多着色器全家桶覆盖
HDRPShaders.unity(HDRPShaders/README.md)覆盖了 HDRP 的Lit、LitTessellation、Unlit、LayeredLit、LayeredLitTessellation以及Shader Graph PBR输出,演示对球体颜色与自发光(emissive)值的覆盖。操作要点:
- 选中LitRedEmissive或UnlitRedEmissive球体,观察其上的 HDRP Material Property Base Color Authoring 与 Emissive Color Authoring 组件;
- 选中LayeredLit或LayeredLitTessellationMagenta,观察其 "Layered Lit Base Color 0 Authoring" 组件——这是 LayeredLitBaseColor0Authoring.cs 脚本,利用 HDRP LayeredLit 的
_BaseColor0关键字逐层覆盖颜色; - 选中PBRBlue球体,其上的 Material Color 组件展示了如何为自定义 Shader Graph 属性编写覆盖组件;
- 点击Edit编辑 Shader Graph,注意 Color 属性的 Node Settings 中开启了Hybrid Per Instanced选项——这是属性可被逐实例覆盖的前提。
ShaderGraphProperties:Shader Graph 属性覆盖
ShaderGraphProperties.unity(ShadergraphProperties/README.md)用使用 Shader Graph PBR 输出的立方体演示覆盖。选中CubeRed观察 Material Color 组件;编辑 Shader Graph 时注意其 Color 属性启用了Override Property Declaration且Shader Declaration设为Hybrid Per Instance。自定义 Shader Graph 属性只有声明为 Hybrid Per Instance,实体上的覆盖组件才能生效。
MaterialOverridesSample:零代码配置覆盖
MaterialOverridesSample.unity(MaterialOverridesSample/README.md)演示完全不用写代码的覆盖方式:球体使用 HDRP Lit、HDRP Unlit 与 Shader Graph 材质;挂在 MeshRenderer 上的MaterialOverride 组件引用一个MaterialOverride 资产,该资产即配置覆盖哪些属性及其值。操作:选中名称含PerInstance的球体,观察 MaterialOverride 组件并点击其引用的资产查看已配置的属性。生成产物即上文展示的HDRPMyColorVector4OverrideOverrideGenerated.cs这类代码,并配套 HDRPMyMetallicFloatOverrideOverrideGenerated.cs(浮点型 metallic)与 HDRPMySmoothnessFloatOverrideOverrideGenerated.cs 等生成文件,可见同一机制同时支撑向量与标量属性。
BuiltInMaterialSHProperties:覆盖内置 SH 属性
BuiltInMaterialSHProperties.unity(BuiltInMaterialSHProperties/README.md)演示覆盖内置材质球谐(SH)属性(即Unity_SH系列)的值。球体由挂在 MeshRenderer 上的 Authoring 组件提供的 LightProbe SH 属性值照明。操作步骤:
- 在 Hierarchy 中选中某个 SubScene(工程内有
SubsceneSHAr / SubsceneSHAg / SubsceneSHAb / SubsceneSHBr / SubsceneSHBg / SubsceneSHBb / SubsceneSHC / SubsceneEmpty等多个子场景,见 BuiltInMaterialSHProperties 目录); - 点击Open打开;
- 选中球体对象,确认MeshRenderer > Probes > Light Probes为Custom Provided;
- 修改
Unity_SH内置材质属性 Authoring 组件上的值,观察球体光照变化; - 保存并关闭 SubScene。
这使开发者可以绕过探针系统,直接用自定义 SH 系数控制实体光照。
混合组件示例(3. Hybrid Components)
HybridEntitiesConversion:SubScene 中的图形伴随组件
HybridEntitiesConversion.unity(HybridEntitiesConversion/README.md)演示可放入 SubScene 的图形相关伴随组件(companion components)。SubScene 中包含灯光(Lights)、体积(Volumes)与其他对象,Entities Graphics 对这些图形组件全部提供支持。需要注意:Particle System 在 SubScene 中不预览,但在运行时能正确模拟。操作上只需打开 SubScene 观察其中的对象与组件布局。
TriggerParticles:从 ECS System 播放 VFX
TriggerParticles.unity(TriggerParticles/README.md)演示如何从 ECS System 播放 VFX Graph:SubScene 内有一个球体与一个 VFX Graph,JumpingSpherePSSystem脚本驱动球体跳跃,并在球体触地瞬间播放 VFX。VFX Graph 烘焙为伴随组件后可从 ECS 脚本访问。核心实现见 JumpingSpherePSSystem.cs:
// 让球体上下跳动:根据时间修改 LocalTransform foreach (var translation in SystemAPI.Query<RefRW<LocalTransform>>().WithAll<JumpingSphereTag>()) { translation.ValueRW.Position = new float3(0, y, 0); } // 触地时播放粒子系统(y < 0.05f) foreach (var particleSystem in SystemAPI.Query<SystemAPI.ManagedAPI.UnityEngineComponent<VisualEffect>>().WithAll<JumpingSpherePSTag>()) { if (y < 0.05f) particleSystem.Value.Play(); }要点:通过SystemAPI.ManagedAPI.UnityEngineComponent<VisualEffect>查询伴随组件引用,配合JumpingSphereTag/JumpingSpherePSTag两个标签(其 Authoring 见 JumpingSpherePSTagAuthoring.cs 与 JumpingSphereTagAuthoring.cs)实现解耦触发。
API 示例(4. API Examples)
EntityCreation:Burst 作业中高效创建渲染实体
EntityCreation.unity(EntityCreation/README.md)演示如何用RenderMeshDescription与RenderMeshUtility.AddComponentsAPI 配合Instantiate高效创建由 Entities Graphics 渲染的实体,并通过 ECS 组件设置颜色。其脚本 TestEntityCreationAPI.cs 是完整可复用的运行时实体创建模板,核心流程如下:
var filterSettings = RenderFilterSettings.Default; filterSettings.ShadowCastingMode = ShadowCastingMode.Off; filterSettings.ReceiveShadows = false; var renderMeshArray = new RenderMeshArray(new[] { Material }, Meshes.ToArray()); var renderMeshDescription = new RenderMeshDescription { FilterSettings = filterSettings, LightProbeUsage = LightProbeUsage.Off, }; // 创建一个"原型实体",一次性添加全部渲染组件 var prototype = entityManager.CreateEntity(); RenderMeshUtility.AddComponents( prototype, entityManager, renderMeshDescription, renderMeshArray, MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0)); entityManager.AddComponentData(prototype, new MaterialColor()); // 在 Burst 并行作业中批量克隆原型实体 var spawnJob = new SpawnJob { Prototype = prototype, Ecb = ecbJob.AsParallelWriter(), // ...配置数量、网格数组、包围盒等 }; var spawnHandle = spawnJob.Schedule(EntityCount, 128);SpawnJob(IJobParallelFor)在Execute内用Ecb.Instantiate克隆原型,再用SetComponent写入每实例不同的LocalToWorld、MaterialColor、MaterialMeshInfo与RenderBounds——其中RenderBounds必须按真实网格设置以保证剔除正确(见MeshBounds数组的构建与Meshes[i].bounds.ToAABB())。场景中默认参数为EntityCount = 10000、ObjectScale = 0.1f、Radius = 10、Twists = 16,选中 Hierarchy 中的Spawner对象即可在 Inspector 中调整这些参数,然后点击 Play 观察生成的彩色球体螺旋。这正是"克隆原型 + Burst 作业 + ECB"的官方推荐高效路径。
RenderMeshUtilityExample:AddComponents 最小示例
RenderMeshUtilityExample.unity(RenderMeshUtilityExample/README.md)是RenderMeshUtility.AddComponents的精简演示,由 AddComponentsExample.cs 实现。与上一示例相比,它展示了:
- 用带命名参数的便捷构造器创建描述:
new RenderMeshDescription(shadowCastingMode: ShadowCastingMode.Off, receiveShadows: false); - 勾选
m_differentMaterial时,为每个实例运行时克隆材质并按 HSV 生成不同颜色(同时设置_Color与_BaseColor,兼容 Built-in 与 HD 管线),构造RenderMeshArray后调用ResetHash128()刷新哈希; - 以
m_w × m_h(默认 30×30)网格布局克隆实体,用MaterialMeshInfo.FromRenderMeshArrayIndices(matIndex, 0)为每实例指定材质索引。
选中Spawner配置Mesh、m_material、m_differentMaterial、m_w、m_h后点 Play 即可看到成片立方体,是理解渲染数组(RenderMeshArray)与实体克隆的最小可运行范例。
MaterialMeshChange:运行时切换材质与网格
MaterialMeshChange.unity(MaterialMeshChange/README.md)含两个实体:一个按帧切换网格、一个切换材质。实现上 MeshChangerAuthoring.cs 与 MaterialChangerAuthoring.cs 是"Authoring + Baker + System"三件套的典范:
- Authoring 组件用
[RegisterBinding(typeof(MeshChanger), "frequency")]等特性把 Inspector 字段绑定到运行时组件,Baker 通过AddComponentObject加入实体(TransformUsageFlags.Dynamic); - 系统在
OnStartRunning中通过World.GetOrCreateSystemManaged<EntitiesGraphicsSystem>()拿到渲染系统,调用RegisterMaterial(material)/RegisterMesh(mesh)得到BatchMaterialID/BatchMeshID; - 在
OnUpdate中每frequency帧翻转active标志,并直接改写MaterialMeshInfo的MaterialID或MeshID实现切换,无需重建实体或材质实例。
操作步骤:打开 SubScene → 选中MeshChange或MaterialChangeGameObject 观察 Authoring 组件 → 关闭 SubScene 进入 Play 模式,两个对象烘焙为实体后由 ECS System 驱动周期性的网格/材质互换。
形变示例(5. Deformation)
前置条件:ENABLE_COMPUTE_DEFORMATIONS 脚本宏
MeshDeformations 与 SkinnedCharacter 两个形变场景都要求在Edit > ProjectSettings > Player > Other Settings的Scripting Define Symbols中添加ENABLE_COMPUTE_DEFORMATIONS定义符号,否则计算着色器形变路径不会编译。这是运行形变示例前必须完成的配置步骤。
MeshDeformations:BlendShape 与蒙皮权重实体
MeshDeformations.unity(MeshDeformations/README.md)用三色网格区分三种形变组合:红色网格用 BlendShape(混合形状)形变,蓝色网格仅用蒙皮(skinning),紫色网格两种方法叠加于同一网格。所有数值与变换都由一套简单动画系统写入 ECS 变换组件,再由 Mesh Deformation 系统据此计算蒙皮矩阵。操作:打开某个 SubScene(BlendShapeSubScene/SkinningSubScene/CombinedSubScene),选中cube_test_mesh对象,确认其材质使用的 Shader Graph 包含 Compute Deformation 节点。
SkinnedCharacter:计算着色器 vs 顶点着色器蒙皮
SkinnedCharacter.unity(SkinnedCharacter/README.md)展示四个使用网格形变的动画角色,同时演示两条蒙皮路径:
- 顶点着色器形变(蓝色角色):Shader Graph 必须使用Linear Blend Skinning 节点;
- 计算着色器形变(粉色角色):Shader Graph 必须使用Compute Deformation 节点。
两个 SubScene(ComputeSubScene/VertexSubScene)分别对应两条路径。选中Geom_Body_LOD0可检查其材质对应的节点设置。底层蒙皮矩阵计算逻辑可参考 CalculateSkinMatrixSystem.cs:它先并行收集BoneTag骨骼的LocalToWorld与RootTag根的逆矩阵(NativeParallelHashMap),然后在CalculateSkinMatricesJob中逐个骨骼执行skinMatrix = rootWorldToLocal * boneLocalToWorld * bindPose,把结果写入DynamicBuffer<SkinMatrix>,并在PresentationSystemGroup中排在DeformationsInPresentation之前执行,供形变系统拾取。配套的简单动画系统(写入LocalTransform)与 Authoring 组件见 CommonAssets/Scripts/SimpleAnimationSystem 目录。
杂项示例(6. Misc)
DisabledEntities:禁用实体与 DisableRendering
DisabledEntities.unity(DisabledEntities/README.md)场景含 3 个立方体,其中 1 个被禁用,因此屏幕只渲染 2 个。要点:禁用实体与在编辑器中禁用 GameObject 无异,禁用会关闭实体的一切;若只想停止渲染而保留其他逻辑,应在 ECS 脚本中给实体添加DisableRendering标签组件。操作:打开 SubScene 选中被禁用的 Cube,在 Inspector 确认其处于 disabled 状态。
LODs:实体的多级细节
LODs.unity(LODs/README.md)用一片立方体网格演示 Entities Graphics 的 LOD,每个 LOD 级用不同颜色区分。操作:打开 SubScene 选中Root对象,其下包含 100 个 LodGroup 子节点,每个子节点都挂有 LOD Group 组件;烘焙后这些 LOD 组会映射为实体的 LOD 组件,由 Entities Graphics 按距离自动切换(配套的 CameraMovement.cs 方便玩家飞行观察切换效果)。
MatrixPrevious:运动矢量与运动模糊
MatrixPrevious.unity(MatrixPrevious/README.md)演示多个实体的移动如何配合 HDRP 运动矢量(Motion Vectors)正确响应运动模糊。场景中球体父级为BallsGameObject,每个球体带 Sphere ID Authoring 组件,由 MoveBallsSystem.cs 逐帧平移:系统先为缺失BallOriginalTranslation的球体记录初始位置,随后调度MoveBall(IJobChunk,Burst 编译)基于ElapsedTime在圆周上平移每个球体(见 SphereIdAuthoring.cs 提供的标识组件)。进入 Play 模式后,球体烘焙为实体并以运动模糊拖尾运动——这验证了 Entities Graphics 会自动维护上一帧矩阵以生成正确的运动矢量。
Submesh:一个实体对应一个材质
Submesh.unity(Submesh/README.md)演示带 3 个子网格的单个 GameObject:其 Mesh 含 3 个 sub-mesh,并配 3 个独立材质。由于 Entities 每个实体只支持一个材质,这类 GameObject 会被烘焙成多个实体(每个材质一个)。操作步骤:
- 确认 SubScene 处于关闭状态;
- 打开Window > Entities > Hierarchy;
- 导航到 SubScene,展开带层级结构的实体;
- 观察由同一 Authoring GameObject 烘焙出的 3 个实体。
TransparencyOrdering:透明实体深度排序
TransparencyOrdering.unity(TransparencyOrdering/README.md)场景含大量半透明立方体,正确的渲染需要从后到前(back-to-front)排序。Entities Graphics 通过DepthSorted_Tag标签组件实现:实体使用透明材质烘焙时,该标签会被自动添加。操作步骤:
- 确认 SubScene 关闭;
- 打开Window > Entities > Hierarchy;
- 选中层级底部的某个实体;
- 观察该实体带有
DepthSorted_Tag标签组件。
该标签提示渲染器按深度排序该批实体,从而获得正确的透明混合结果。
总结:从示例场景到生产实践的映射
结合全部 20 个特性场景(HDRPSamples 主 README)与仓库源码,可以归纳出 Entities Graphics + HDRP 生产环境下的几条关键实践路径:
- 光照一体化:SubScene 中的灯光、探针、光照贴图均可烘焙为 ECS 数据(
1. Lighting),Static/非 Static 的组合决定烘焙方式; - 逐实例渲染差异化:
[MaterialProperty]组件、MaterialOverride 资产、Hybrid Per Instance 声明三位一体(2. MaterialProperties),是替代"复制材质"的高效方案; - 运行时动态内容:
RenderMeshUtility.AddComponents+ 原型克隆 + Burst 作业是官方推荐的高效实体创建路径(4. API Examples),RegisterMaterial/RegisterMesh支持运行时无重建地切换材质网格; - 高级渲染特性:形变(BlendShape/蒙皮)、LOD、运动矢量、透明排序、子网格拆分等均有专门场景验证(
5. Deformation、6. Misc)。
每个场景目录下都配有独立 README 与可直接运行的 Authoring/System 源码,是学习 Entities Graphics 1.4.x + HDRP 17.x 组合特性的最佳教材:先在 Base.unity 中播放切换全部场景,再针对感兴趣的类别打开 SubScene 查看组件配置,最后对照本文给出的源码路径深入阅读实现,即可快速掌握这套渲染栈的核心用法。
【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考