Unity ECS Mesh Deformations 示例解析:BlendShape 与蒙皮变形的完整数据管线

发布时间:2026/9/16 17:18:08
Unity ECS Mesh Deformations 示例解析:BlendShape 与蒙皮变形的完整数据管线
Unity ECS Mesh Deformations 示例解析BlendShape 与蒙皮变形的完整数据管线【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples导读本文围绕 HDRPSamples 中的Mesh Deformations示例场景展开讲解 Unity ECSEntities 1.0 Graphics 包中网格变形的两大核心机制BlendShape 形变与蒙皮Skinning变形。你将看到示例如何用红、蓝、紫三色网格分别演示仅 BlendShape仅蒙皮两者叠加三种效果并深入剖析背后的完整数据管线——从 Authoring 组件、Baker 烘焙、ECS 变换组件动画到骨骼矩阵计算、Shader Graph 变形节点渲染最后给出可直接照做的运行步骤与常见配置要点。示例展示什么三种变形方式的同屏对照进入 Play 模式即可看到一系列应用了常见网格变形组合的网格红色网格仅使用BlendShape融合变形驱动顶点位置随 BlendShape weight 变化蓝色网格仅使用蒙皮Skinning顶点由骨骼变换驱动紫色网格同一网格上同时叠加两种方法即既有 BlendShape 形变又有蒙皮形变。所有数值与变换都由一个极简的动画系统驱动该系统直接写入 ECS 变换组件LocalTransform等随后CalculateSkinMatrixSystem基于这些变换计算皮肤矩阵最终被 Mesh Deformation 系统拾取并应用到渲染上。对应的场景与资源位于仓库GraphicsSamples/HDRPSamples/Assets/SampleScenes/5. Deformation/MeshDeformations/其中MeshDeformations.unity—— 主场景Subscenes/BlendShapeSubScene.unity—— 演示 BlendShape 变形的子场景Subscenes/SkinningSubScene.unity—— 演示蒙皮变形的子场景Subscenes/CombinedSubScene.unity—— 演示两者叠加的子场景Models/—— 三个基础 FBX 模型basic_blendshapes_test.fbx、basic_skinning_test.fbx、basic_combined_test.fbx。运行示例的完整操作步骤步骤 1添加 ENABLE_COMPUTE_DEFORMATIONS 脚本宏这是整个示例能否正确渲染的前提条件。打开菜单Edit ProjectSettings Player Other Settings在Scripting Define Symbols列表中添加ENABLE_COMPUTE_DEFORMATIONS该宏控制的是**计算着色器变形compute deformation**路径是否启用。示例中的紫色叠加网格与 BlendShape 演示都依赖 Compute Deformation 节点因此必须开启此宏。若缺失该宏相关材质在运行时无法被变形系统正确驱动。步骤 2打开并进入子场景在 Hierarchy 中选择任意一个 Subscene如BlendShapeSubScene在 Inspector 中点击Open打开子场景进行编辑直接进入 Play 模式即可观察动画效果。步骤 3确认材质使用 Compute Deformation 节点在子场景中选中cube_test_mesh对象注意其材质必须使用包含 Compute Deformation 节点的 Shader Graph。本示例对应的两个 Shader Graph 与材质文件位于GraphicsSamples/HDRPSamples/Assets/SampleScenes/5. Deformation/CommonAssets/Materials/ComputeDeformShader.shadergraph/ComputeDeformMaterial.mat—— 计算着色器变形路径需开启ENABLE_COMPUTE_DEFORMATIONSVertexDeformShader.shadergraph/VertexDeformMaterial.mat—— 顶点着色器变形路径使用 Linear Blend Skinning 节点无需计算宏。两条路径的区别在于顶点变形计算发生在顶点着色器还是计算着色器中。如果你自行制作变形材质需要保证 Shader Graph 中接入Deformation节点Compute Deformation 或 Linear Blend Skinning否则网格不会产生任何形变。数据管线全景从 Authoring 到渲染把示例拆开看一条完整的网格变形数据流可以归纳为四个阶段仓库中的源码正好一一对应阶段作用仓库实现Authoring在 GameObject 上声明动画参数起始/目标值、周期、相位偏移CommonAssets/Scripts/SimpleAnimationSystem/Hybrid/Animate*Authoring.csBaking将 Authoring 组件转换为 ECS 组件并读取 SkinnedMeshRenderer 的骨骼/绑定姿势SimpleAnimationBakingSystem.csRuntime 动画系统每帧用正弦函数插值写入 ECS 变换组件与 BlendShapeWeightSimpleAnimationSystems.cs皮肤矩阵计算由骨骼 LocalToWorld、根节点逆矩阵与绑定姿势合成 SkinMatrixCalculateSkinMatrixSystem.cs下面逐层展开。深入一简单动画系统——Authoring 组件与 Baker 转换Authoring 组件示例为位置、旋转、缩放、BlendShape 各准备了一个 MonoBehaviour统一暴露四个参数参数含义默认值以 AnimateBlendShape 为例From / FromWeight动画起始值BlendShapeFromWeight 0To / ToWeight动画目标值BlendShapeToWeight 100Phase完成一个完整动画循环所需的秒数Phase 1Offset相位偏移取值范围[0, 1]表示占一个周期的百分比Offset 0源码见 AnimateBlendShapeAuthoring.cs、AnimatePositionAuthoring.cs、AnimateRotationAuthoring.cs默认从-10°旋转到10°周期 5 秒、AnimateScaleAuthoring.cs默认从Vector3.one缩放到2 * Vector3.one。Baker把参数换算成运行时组件在 SimpleAnimationBakingSystem.cs 中四个 Baker 把 Authoring 参数换算为运行时 ECS 组件关键换算关系如下以位置动画为例var positionAnimation new AnimatePosition { From authoring.FromPosition, To authoring.ToPosition, Frequency 1f / authoring.Phase, // 周期 → 频率 PhaseShift authoring.Offset * authoring.Phase, // 百分比偏移 → 时间偏移 }; var entity GetEntity(TransformUsageFlags.Dynamic); AddComponent(entity, positionAnimation); AddComponentLocalTransform(entity);对应运行时组件定义在 SimpleAnimationComponents.csAnimatePositionfloat3 From/To、AnimateRotationquaternion From/To、AnimateScalefloat3 From/To、AnimateBlendShapefloat From/To各含Frequency与PhaseShift蒙皮相关BoneTag、RootTag、RootEntity指向根骨骼实体、BoneEntity缓冲存储每个骨骼的实体引用、BindPose缓冲存储每个骨骼的绑定姿势矩阵。运行时系统正弦插值驱动变换四个系统分别位于 SimpleAnimationSystems.cs均标注[UpdateBefore(typeof(TransformSystemGroup))]确保在变换系统之前写入AnimateBlendShapeWeightSystem写DynamicBufferBlendShapeWeightAnimatePositionSystem写LocalTransform.PositionAnimateRotationSystem写LocalTransform.Rotation四元数使用slerpAnimateScaleSystem写PostTransformMatrix。所有系统共用同一条归一化时间曲线以 BlendShape 系统为例const float k_Two_Pi 2f * math.PI; var interpolation 0.5f * (math.sin(k_Two_Pi * frequency * (ElapsedTime phase)) 1f); var weight math.lerp(data.From, data.To, interpolation);即用sin曲线把时间映射到[0, 1]区间再在 From/To 之间做线性插值——运动呈平滑往复的正弦节奏无需任何关键帧动画文件。深入二皮肤矩阵计算系统——蒙皮变形的核心数学蒙皮变形的关键在于把每根骨骼的世界变换转成以根节点为基准、再叠加绑定姿势的皮肤矩阵。整个计算在 CalculateSkinMatrixSystem.cs 中完成该系统挂载在PresentationSystemGroup内并声明[UpdateBefore(typeof(DeformationsInPresentation))]保证在网格变形系统之前产出最新皮肤矩阵。其计算逻辑分三步对应CalculateSkinMatricesJob.Execute的循环体// 1. 取骨骼的世界矩阵 var matrix bonesLocalToWorld[boneEntity]; // 2. 转换到根节点坐标系 var rootMatrixInv rootWorldToLocal[rootEntity]; matrix math.mul(rootMatrixInv, matrix); // 3. 叠加绑定姿势得到最终皮肤矩阵 var bindPose bindPoses[i].Value; matrix math.mul(matrix, bindPose); // 写入 SkinMatrixfloat3x4 skinMatrices[i] new SkinMatrix { Value new float3x4(matrix.c0.xyz, matrix.c1.xyz, matrix.c2.xyz, matrix.c3.xyz) };骨架数据在每帧更新前通过两个并行 Job 收集到NativeParallelHashMapEntity, float4x4中GatherBoneTransformsBoneJob[WithAll(typeof(BoneTag))]收集每根骨骼的LocalToWorldGatherBoneTransformsRootJob[WithAll(typeof(RootTag))]收集根节点的LocalToWorld并求逆得到根坐标系到世界的逆矩阵用于把骨骼矩阵拉回根节点局部空间。Job 调度顺序两个收集 Job 并行 →JobHandle.CombineDependencies合并依赖 →CalculateSkinMatricesJob并行执行 → 最后合并释放两个 HashMap 的依赖句柄。可见整套流程是完全 ECS 原生、可并行的实现没有依赖 Unity 传统 Animation 组件。深入三SkinnedMeshRenderer 如何进入 ECSDeformationSampleBaker同样位于SimpleAnimationBakingSystem.cs负责把 GameObject 侧的SkinnedMeshRenderer数据搬进 ECS读取skinnedMeshRenderer.bones与sharedMesh.bindposes只有两者都非空才走蒙皮分支为网格实体添加RootEntity指向rootBone无 rootBone 时退回自身 transform添加BoneEntity与BindPose两个动态缓冲逐骨骼填充实体引用与绑定姿势矩阵DependsOn(skinnedMeshRenderer.sharedMesh)声明对网格资源的依赖确保资源改动会触发重新烘焙。此外ComputeSkinMatricesBakingSystem一个WorldSystemFilterFlags.BakingSystem系统在烘焙阶段为根骨骼实体添加LocalToWorld与RootTag为所有骨骼实体添加BoneTag遍历AdditionalEntitiesBakingData为渲染实体覆写材质基色HDRPMaterialPropertyBaseColor实现示例中红/蓝/紫的着色区分颜色源头来自DeformationsSampleAuthoring组件的Color字段默认值约为(0.9, 0.3, 0.5)可在 Inspector 中修改。这里也解释了为什么示例中同一网格能同时呈现两种变形basic_combined_test.fbx同时带有 BlendShape 通道与骨骼蒙皮数据两类运行时组件BlendShapeWeight与SkinMatrix都会附加到实体上渲染时分别生效。与 SkinnedCharacter 示例的对比同目录下还有另一个示例 SkinnedCharacter演示四个动画角色网格粉色角色走 Compute Shader 变形蓝色角色走顶点着色器变形。两个示例共用同一套动画与皮肤矩阵计算源码CommonAssets/Scripts/SimpleAnimationSystem/区别只在材质使用的节点顶点蒙皮必须使用Linear Blend Skinning 节点计算蒙皮必须使用Compute Deformation 节点依赖ENABLE_COMPUTE_DEFORMATIONS宏。因此 MeshDeformations 可视为机制教学SkinnedCharacter 则是角色落地两者配合可以完整覆盖基础实验 → 生产化角色两条路径。常见问题与排查要点网格不变形优先检查是否已添加ENABLE_COMPUTE_DEFORMATIONS宏再检查材质是否真正接入了 Compute Deformation / Linear Blend Skinning 节点仅使用普通 Lit 材质不会产生变形。颜色不对变形示例的着色由DeformationsSampleAuthoring的Color与烘焙系统的HDRPMaterialPropertyBaseColor覆写决定改动需重新进入烘焙或 Play 模式才生效。骨骼抖动/错位确认rootBone设置正确。源码中根骨骼选取逻辑是优先skinnedMeshRenderer.rootBone否则退回transform见DeformationSampleBaker根节点一旦缺失或错误皮肤矩阵将整体偏移。动画节奏调节所有动画共用Phase周期秒数与Offset周期百分比相位偏移两个旋钮Frequency 1 / Phase修改后重进 Play 即生效无需重写任何代码。如需进一步深入可在当前仓库的 GraphicsSamples/HDRPSamples/Assets/SampleScenes/5. Deformation/ 目录下继续研读全部源码、材质与 Shader Graph或对照com.unity.entities.graphics包自带的 Mesh Deformations 手册章节了解更底层的DeformationsInPresentation系统调度细节。【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考