
Entities Graphics 运行时高效创建实体EntityCreation 样本深度解析【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples本技术指南围绕 Unity DOTS 官方样本仓库 EntityComponentSystemSamples 中的 EntityCreation 场景展开讲解如何基于RenderMeshUtility.AddComponents与RenderMeshDescriptionAPI在运行时通过 Burst 并行 Job 批量实例化实体并通过MaterialColor等 ECS 组件实现逐实体着色。读完本文你将掌握一套原型实体 RenderMeshArray EntityCommandBuffer的高效实体生成范式并理解其渲染裁剪、内存与性能设计背后的原理。样本概览EntityCreation 是 HDRP Entities Graphics 功能样本之一位于 GraphicsSamples/HDRPSamples/Assets/SampleScenes/4. API Examples/EntityCreation对应的场景文件为EntityCreation.unity。该样本的核心目标是在运行期高效创建经由 Entities Graphics 渲染的实体并通过 ECS 组件设置颜色。进入 Play 模式即可看到生成结果——数量可配的实体沿螺旋状排列色相沿路径平滑渐变。仓库同时提供了功能一致的 URP 版本样本GraphicsSamples/URPSamples/Assets/SampleScenes/4. API Examples/EntityCreation两处 TestEntityCreationAPI.cs 源码完全一致说明该方案与渲染管线HDRP/URP无关属于 Entities Graphics 的通用运行时 API。样本的运行结果如上图所示一万个实体沿扭曲的螺旋柱面分布颜色由 HSV 色相随索引位置线性变化直观展示了单个原型批量实例化 ECS 组件逐实体差异化的组合效果。核心 APIRenderMeshUtility 与 RenderMeshDescription样本 README 明确指出核心逻辑由TestEntityCreationAPI脚本完成它组合使用了RenderMeshDescription、RenderMeshUtility.AddComponents与Instantiate实体实例化三个要素。RenderMeshUtility.AddComponents是 Entities Graphics 提供的运行时实体渲染组件装配 API其作用等价于把 GameObject 转实体GameObject Conversion流程中的渲染相关组件一次性附加到目标实体上避免手写一长串AddComponent调用。调用时通常配合两个数据载体RenderMeshArray维护一组材质Material与一组网格Mesh的扁平索引数组供实体以数组下标方式引用避免为每个实体单独持有资源引用RenderMeshDescription描述实体的渲染设置包括阴影投射/接收、光照探针Light Probe等过滤选项。从源码可见其典型用法TestEntityCreationAPI.csvar 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());这段代码先以默认值构造RenderFilterSettings关闭阴影投射与阴影接收样本为性能演示场景不需要阴影再基于单一材质与多网格构建RenderMeshArray随后创建一个裸实体作为原型把渲染组件一次性装配到原型上。其中MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0)表示该实体默认引用 RenderMeshArray 中下标为 0 的材质与 0 号网格——注意这里的网格下标是运行时可通过SetComponent动态改写的见下文 SpawnJob。与该样本同目录下的 RenderMeshUtilityExample 展示了RenderMeshUtility.AddComponents的另一类用法——通过运行时创建的材质与材质属性设置实现着色可作为本样本的进阶参考。原型实体 并行 Job 的批量生成范式样本的生成策略分为两个阶段先在主线程准备好一个带完整渲染组件的原型实体再在 Burst 并行 Job 中通过EntityCommandBuffer.ParallelWriter批量克隆该原型。注释对此做了明确说明通过克隆预先创建的原型实体来生成大部分实体原型可以是 Prefab也可以是像本样本这样在运行时创建的实体这是运行时创建实体最快、最高效的方式TestEntityCreationAPI.cs。SpawnJob一次 Job 完成实例化与差异化SpawnJob是一个IJobParallelFor结构体每个 index 对应一个待生成的实体[GenerateTestsForBurstCompatibility] public struct SpawnJob : IJobParallelFor { public Entity Prototype; public int EntityCount; public int MeshCount; public float ObjectScale; public float Radius; public float Twists; public EntityCommandBuffer.ParallelWriter Ecb; [ReadOnly] public NativeArrayRenderBounds MeshBounds; public void Execute(int index) { var e Ecb.Instantiate(index, Prototype); // Prototype has all correct components up front, can use SetComponent Ecb.SetComponent(index, e, new LocalToWorld {Value ComputeTransform(index)}); Ecb.SetComponent(index, e, new MaterialColor() {Value ComputeColor(index)}); // MeshBounds must be set according to the actual mesh for culling to work. int meshIndex index % MeshCount; Ecb.SetComponent(index, e, MaterialMeshInfo.FromRenderMeshArrayIndices(0, meshIndex)); Ecb.SetComponent(index, e, MeshBounds[meshIndex]); } // ComputeTransform / ComputeColor 见源码 }关键点逐一拆解Ecb.Instantiate(index, Prototype)克隆原型实体。由于原型已具备全部渲染组件克隆体会自动继承这些组件因此后续只需用SetComponent覆盖差异无需再走AddComponent。LocalToWorld由ComputeTransform(index)计算。从源码看位置采用球坐标变换——r sin(t·π)·Radius让实体沿柱面半径收缩、phi t·Twists·2π产生扭转、y方向线性铺开最终构成螺旋扭曲的立体分布。MaterialColor由ComputeColor(index)基于Color.HSVToRGB(t, 1, 1)计算t index / (EntityCount - 1)把色相从 0 线性映射到 1形成彩虹渐变。这正是样本 README 提到的通过 ECS 组件设置颜色的实现——颜色被写入MaterialColor组件由 Entities Graphics 自动驱动材质_BaseColor/_Color属性。MaterialMeshInfo.FromRenderMeshArrayIndices(0, meshIndex)按index % MeshCount循环切换网格让不同实体引用 RenderMeshArray 中的不同 Mesh验证了网格下标可逐实体运行时改写。MeshBounds[meshIndex]把每个网格的RenderBounds渲染包围盒写入实体。源码注释明确指出MeshBounds 必须根据实际网格设置裁剪culling才能正常工作TestEntityCreationAPI.cs。渲染器靠该组件做视锥/遮挡剔除若缺失或错误实体会被错误裁剪掉。包围盒预计算与 Job 调度主线程在启动 Job 前先把每个 Mesh 的包围盒转成 ECS 的RenderBoundsAABB存入NativeArrayJob 中以[ReadOnly]只读引用var bounds new NativeArrayRenderBounds(Meshes.Count, Allocator.TempJob); for (int i 0; i bounds.Length; i) bounds[i] new RenderBounds {Value Meshes[i].bounds.ToAABB()}; var spawnHandle spawnJob.Schedule(EntityCount, 128); bounds.Dispose(spawnHandle); // 让 Job 完成后自动回收 spawnHandle.Complete();spawnJob.Schedule(EntityCount, 128)以批大小 128 将EntityCount次迭代并行化全部由 Burst 编译执行因此可以轻松在单帧内生成上万个实体。bounds.Dispose(spawnHandle)把原生内存释放挂接到 Job 句柄上Job 执行完毕即自动释放避免主线程Complete()前手动管理。ECB 回放与原型销毁Job 本身不直接操作EntityManager而是写入EntityCommandBuffer.ParallelWriter保证线程安全ecbJob.Playback(entityManager); // 将 ECB 中的操作应用回 EntityManager ecbJob.Dispose(); // 释放 ECB 自身内存 entityManager.DestroyEntity(prototype); // 原型实体不再需要销毁Playback在主线程执行统一完成实例化与组件设置随后销毁原型实体避免其残留场景中产生多余渲染。整个流程体现了 ECS 的核心纪律写操作集中在主线程回放并行 Job 只做无冲突的并行记录。场景配置与操作步骤场景EntityCreation.unity中挂载TestEntityCreationAPI的SpawnerGameObject 已预置了样本默认参数EntityCreation.unity参数默认值作用EntityCount10000生成实体总数直接决定 Job 迭代次数与实例数量ObjectScale0.1实体缩放float3(ObjectScale)作为 TRS 缩放入参Radius10螺旋柱面的最大半径Twists16螺旋扭转圈数phi角随t的倍数Meshes4 个 Mesh供实体轮换引用的网格集合Material1 个材质渲染材质实体共用一个材质实例样本 README 给出的使用步骤非常简洁按如下操作即可复现在 Hierarchy 中选中Spawner在 Inspector 中配置上述参数可调整实体数量、缩放、半径、扭转圈数或增删 Mesh点击 Play。进入 Play 后Start()一次性完成原型创建、Job 调度与回放随后所有实体持续由 Entities Graphics 渲染。注意该脚本只负责一次性生成Update()为空实体生成后不会继续更新变换如需动态改变可另写 System 修改LocalToWorld、MaterialColor或MaterialMeshInfo组件。性能设计要点总结综合源码可以提炼出这套运行时批量建实体方案的四个关键实践原型复用代替逐个装配先装配好一个原型实体可来自 Prefab 或运行时创建再批量Instantiate把成本高昂的组件装配只执行一次并行 Job 代替主线程循环通过IJobParallelForEntityCommandBuffer.ParallelWriter实体创建本身被 Burst 并行化主线程只做最后的 ECB 回放数组索引代替资源引用RenderMeshArray让所有实体共享同一份材质/网格索引配合MaterialMeshInfo运行时切换既节省内存又支持差异化外观组件契约完整原型实体组件齐全、只改值不改结构配合正确的RenderBounds保证渲染与裁剪行为符合预期。需要说明的是本样本的TestEntityCreationAPI是演示用MonoBehaviour通过World.DefaultGameObjectInjectionWorld获取 EntityManager生产级代码通常会把生成逻辑放入 ECS System如SystemBaseJobHandle中管理但原型 并行 Job ECB的核心模式完全一致可直接迁移。仓库中同目录的 RenderMeshUtilityExample 与 MaterialMeshChange 等样本分别覆盖了运行时材质属性与运行时换材换网格的场景与本样本互补适合继续深入阅读。【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考