Licensing

将 Spine 官方运行时整合到自建应用程序中需要持有 Spine 许可证.

spine-unity 运行时文档

工具组件

SkeletonRootMotion

spine-unity中的三种Spine skeleton组件均支持root motion. SkeletonRootMotion 组件可以附加到带有SkeletonAnimationSkeletonGraphic (UI) 组件的GameObjects上, 同时为SkeletonMecanim单独提供了 SkeletonMecanimRootMotion 组件. 这个root motion组件类似于在Unity Mecanim的 Animator 组件上启用 Apply Root Motion 选项. 当启用了这个选项后, 运行时会根据动画里 Root Motion Bone 的运动来更改角色位置.

请注意: SkeletonMecanimRootMotion 组件仅能用于 SkeletonMecanim 对象. 将它用于 SkeletonAnimationSkeletonGraphic (UI) 组件时, SkeletonRootMotion 组件将无法正常工作.

参数

  • Root Motion Bone. 该参数指定root motion的目标骨骼, 该骨骼的运动将驱动root motion.
  • X. 启用后, 局部的横向(X轴)运动将用于root motion.
  • Y. 启用后, 局部的纵向(Y轴)运动将用于root motion.
  • Root Motion Scale (X). 缩放横向root motion移动变化量(delta). 可用于修正delta, 例如将一个跳跃动画拉伸到某个特定距离.
  • Root Motion Scale (Y) 缩放纵向root motion移动变化量. 可用于修正delta, 例如将一个跳跃动画拉伸到某个特定高度.
  • Animation Tracks. 可以指定root motion的计算中应该包含哪些 动画轨道.

可选参数

  • Rigidbody2D. 当指定了 Rigidbody2D 组件后, 运行时将基于物理计算把运动应用于 Rigidbody2D 而不是 Transform 组件. 因此建议将检查器里skeleton动画组件的 Advanced - Animation Update 参数置为 In FixedUpdate.
  • Rigidbody. 当指定了 Rigidbody 组件后, 运行时将基于物理计算把运动应用于 Rigidbody 而不是 Transform 组件. 因此建议将检查器里skeleton动画组件的 Advanced - Animation Update 参数置为 In FixedUpdate.

请注意: SkeletonRootMotion 类提供了 AdjustRootMotionToDistance() 及其他方法来修正Delta. Delta修正在特定场景下 (例如将一个跳跃动画拉伸到一个特定距离) 会很有帮助. 你既可在动画开始时调整Root motion, 也可以用 skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex); 每帧都调整Root motion.

SkeletonMecanimRootMotion

该组件是SkeletonMecanim版的 SkeletonRootMotion 组件, 搭配 SkeletonMecanim 组件使用.

当启用了Unity Mecanim AnimatorApply Root Motion 选项时, 运行时会将 SkeletonMecanimRootMotion 组件自动添加到skeleton的GameObject上. 必须先禁用Animator的 Apply Root Motion 选项, 才能移除 SkeletonMecanimRootMotion 组件.

参数

  • Root Motion Bone. 该参数指定root motion的目标骨骼, 该骨骼的运动将驱动root motion.
  • X. 启用后, 局部的横向(X轴)运动将用于root motion.
  • Y. 启用后, 局部的纵向(Y轴)运动将用于root motion.
  • Root Motion Scale (X). 缩放横向root motion移动变化量(delta). 可用于修正delta, 例如将一个跳跃动画拉伸到某个特定距离.
  • Root Motion Scale (Y) 缩放纵向root motion移动变化量. 可用于修正delta, 例如将一个跳跃动画拉伸到某个特定高度.
  • Mecanim Layers. 可以指定root motion的计算中应该包含哪些 Mecanim图层.

可选参数

  • Rigidbody2D. 当指定了 Rigidbody2D 组件后, 运行时将基于物理计算把运动应用于 Rigidbody2D 而不是 Transform 组件.
  • Rigidbody. 当指定了 Rigidbody 组件后, 运行时将基于物理计算把运动应用于 Rigidbody 而不是 Transform 组件.

请注意: SkeletonMecanimRootMotion 类提供了 AdjustRootMotionToDistance() 及其他方法来修正Delta. Delta修正在特定场景下 (例如将一个跳跃动画拉伸到一个特定距离) 会很有帮助. 你既可在动画开始时调整Root motion, 也可以用 skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex); 每帧都调整Root motion.

BoneFollower

该组件会引用 SkeletonAnimation 组件中的一根骨骼, 并在每次 Update 时将自己的transform置为该骨骼的transform.

请注意: SkeletonGraphic 对象有自己专用的 BoneFollowerGraphic 组件.

SkeletonUtilityBone 组件不同, BoneFollower 可以作为一个单独的GameObject使用, 无需任何父级骨骼对象.

使用该组件可以让粒子系统这样的对象跟随skeleton上的某根骨骼.

你可以在示例场景 Spine Examples/Getting Started/4 Object Oriented Sample 中查看如何设置 BoneFollower 组件.

BoneFollowerGraphic

该组件为 SkeletonGraphic 版的 Bone Follower 组件, 需搭配 SkeletonGraphic 组件使用.

SkeletonUtilityBone 组件不同, BoneFollowerGraphic 可以作为一个单独的GameObject使用, 无需任何父级骨骼对象.

使用该组件可以让粒子系统这样的对象跟随skeleton上的某根骨骼.

你可以在示例场景 Spine Examples/Getting Started/6 Skeleton Graphic 中查看如何设置BoneFollowerGraphic 组件.

PointFollower

该组件类似于 Bone Follower 组件, 但它跟随的是一个 PointAttachment 而非某根骨骼.

SkeletonUtilityBone 组件不同, PointFollower 可以作为一个单独的GameObject使用, 无需任何父级骨骼对象.

BoundingBoxFollower

该组件跟随的是skeleton槽位中的某个 边界框(bounding box). 它会获取边界外型并将其传递给 PolygonCollider2D, 然后在每帧启用或禁用它来匹配当前动画.

请注意: 它不会自动跟随骨骼位置, 因此它通常搭配 BoneFollower 组件一起使用. 你可以在 BoundingBoxFollower 检查器中使用 Add Bone Follower 按钮来直接创建一个 BoneFollower 组件.

请注意: 组件不会跟随顶点变形动画(边界框顶点会随时间移动的动画), 组件只会跟随边界框的初始形状.

更多信息请参见 Bone Follower 一节.

SkeletonUtilityBone

有时候需要在运行中程序化地修改骨骼位置, 以便对物理运动或用户输入做出反应.

SkeletonUtilityBone 组件提供了一个方便的接口, 既能让GameObjects跟随某根骨骼位置, 又能手动地或基于2D/3D物理运动修改某根骨骼的位置. 它可以配置为 跟随(follow) 骨骼局部位置, 也能配置为在每次 Update覆盖(override) 骨骼位置. 当设置是 Override 时, 该组件将在SkeletonAnimation 组件更新世界transform之前设置骨骼位置.

重要提示: SkeletonUtilityBone 使用局部transform. 这个transform与 SkeletonUtilityBone GameObjects的层次结构相关, 而该组件的GameObject层级结构正是skeleton层次结构的体现. 快速创建SkeletonUtilityBone 层次结构的推荐方法是使用 下文所述SkeletonUtility 组件.

SkeletonUtilityBone 的检查器也有一个界面来 (选择性或递归地) 创建额外的子骨骼或创建 2D 和3D铰链(hinge chain).

当创建了 SkeletonUtilityBones 的层次结构后, 层次结构面板会在 SkeletonUtilityBone GameObject旁边显示不同的图标, 这两种图标对应的设置是

  • Follow: Follow
  • 或者 Override: Override

示例用例

如果你需要让用户拖动skeleton的某根骨骼, 请在 Override 模式下使用 SkeletonUtilityBone.

但如果只需要让一个GameObject跟随某根骨骼的位置, 则应使用 BoneFollower 组件来节省资源.

示例场景

你可以在 Spine Examples/Other Examples/SkeletonUtility Animated Physics 中找到一个演示了 SkeletonUtilityBone 用法的示例场景. 它展示了如何将 SkeletonUtilityBones 中的某些节点配置为 Follow, 并在层次结构中作为 Override 节点的父节点.

2D与3D物理铰链

Hinge Chain Demo

你有时需要为你角色的披风添加物理效果, 让角色拖拽重物或者给他装个流星锤. spine-unity运行时可以从已有的 SkeletonUtilityBone 层次结构 (见 创建SkeletonUtilityBones的层次结构 一节) 中生成 HingeJointHingeJoint2D 的物理绑定(physics rig).

Hinge Chain Setup

选中一根骨骼作为首个 SkeletonUtilityBone 铰链条目, 然后在检查器中点击 Create 3D Hinge ChainCreate 2D Hinge Chain 就能生成物理绑定. 被选中的骨骼和其所有的 SkeletonUtilityBone 子节点都会被转换为一条铰链. 此后你便可以调整Rigidbody的阻力(drag)和质量(mass)参数来调整效果. 提高阻力值将使Rigidbody移动得更慢, 可以创造出物体沉重甚至风阻效果.

请注意, 铰链的根节点不再以skeleton的骨骼为父节点, 而是被放置到场景层级的顶层中. 这是基于在Unity中正确计算动量的需要. 请勿把铰链根节点再放回skeleton的骨骼层级中, 否则skeleton的运动将不再与铰链联动!

3D铰链

  1. 创建 SkeletonUtilityBone的层次结构.
  2. 在场景面板中选中一根骨骼作为首个铰链条目, 然后在检查器中选择 Create 3D Hinge Chain 来创建3D铰链绑定. Create Hinge Chain 3D
  3. 这会使先前的父对象 (在本例中为 cape-root) 移除铰链的GameObjects, 并在场景层级中新建一个 HingeChain Parent GameObject. 正如前文中所警示的: 切勿将该GameObject重新放回到skeleton中去! Hinge Chain 3D Hierarchy
  4. 调整铰链中节点的Rigidbody的阻力和质量参数来实现你所需的效果.

Skeleton翻转后, HingeChain Parent GameObject将自动旋转180度, 使铰链适应翻转后的骨骼位置.

2D铰链

  1. 创建 SkeletonUtilityBone的层次结构.
  2. 在场景面板中选中一根骨骼作为首个铰链条目, 然后在检查器中选择 Create 2D Hinge Chain 来创建2D铰链绑定. Create Hinge Chain 2D
  3. 这会使先前的父对象 (在本例中为 cape-root) 移除铰链的GameObjects, 并在场景层级中新建一个 HingeChain Parent GameObject. 正如前文中所警示的: 切勿将该GameObject重新放回到skeleton中去! Hinge Chain 2D Hierarchy
  4. 调整铰链中节点的Rigidbody2D的阻力和质量参数来实现你所需的效果.

要注意该GameObject包含两个子对象: Hinge ChainHinge Chain FlippedX. 翻转了skeleton后, 这些GameObjects将根据当前朝向自动启用或停用对应子对象.

SkeletonUtility

创建SkeletonUtilityBones的层次结构

SkeletonUtility 组件提供了一个快速创建 SkeletonUtilityBone GameObjects层次结构的方法, 该层次结构是对skeleton中骨骼层次结构的映射.

添加 SkeletonUtility 组件的步骤: 选中 SkeletonAnimation 组件, 在检查器中展开 Advanced 部分并点击 Add Skeleton Utility. 该组件创建后, Add Skeleton Utility 按钮将消失, 而 SkeletonUtility 组件将被附加到GameObject上.

SkeletonUtility 组件中有一个 Spawn Hierarchy 按钮, 点击后会出现以下选项:

  1. Follow all bones 意在为层次结构中的所有骨骼创建 SkeletonUtilityBone GameObject, 并将其置为 Follow 模式
  2. Follow (Root Only) 只创建根 SkeletonUtilityBone GameObject, 并将其置为 Follow 模式
  3. Override all bones 会为层次结构中的所有骨骼创建 SkeletonUtilityBone GameObject, 并将其置为 Override 模式
  4. Override (Root Only) 只创建根 SkeletonUtilityBone GameObject, 并将其置为 Override 模式

每个 SkeletonUtilityBone 都能配置为覆盖skeleton的任意骨骼位置.

请注意: Spawn Hierarchy 功能只是生成大致结构, 你也能稍后在 SkeletonUtilityBone 检查器中添加额外的 SkeletonUtilityBone GameObjects. 之后删除多余的 SkeletonUtilityBone GameObjects来节省资源也可以. 只需记住务必要保持父子关系不变, 因此切勿删除层次结构中的GameObjects或改变其父节点.

SkeletonUtilityConstraint

C#

它是skeleton约束工具子类的基类. 它会自动在父类 SkeletonUtility 中注册自己并进行相应的更新.

关于如何编写自定义约束类的指南, 请参见示例约束类 SkeletonUtilityGroundConstraintSkeletonUtilityEyeConstraint 的代码.

示例场景

spine-unity运行时内置了演示上文中两个约束类的示例场景. 你可以在 Spine Examples/Other Examples/SkeletonUtility GroundConstraintSpine Examples/Other Examples/SkeletonUtility Eyes 中找到它们.

SkeletonRendererCustomMaterials

用于覆盖某个skeleton实例的material或者某个槽位的material. 该组件提供了一个检查器界面, 可以在SkeletonRenderer 组件(包括其子类 SkeletonAnimationSkeletonMecanim) 上覆盖自定义的material.

右击 SkeletonRenderer 组件(包括其子类 SkeletonAnimationSkeletonMecanim), 并选择 Add Basic Serialized Custom Materials 可以将该组件添加到渲染器中. 在 Custom Slot Materials 数组中添加条目就能覆盖某个槽位的material, 如果条目添加在 Custom Material Overrides 数组中, 可以替换掉整个skeleton当前的material. 请确保禁用了 Override Disabled 选项, 这样才能让各条目中设置的material覆盖生效.

请注意: 该组件的设计初衷里不包括用代码控制Material覆盖. 如果需要通过代码动态地设置SkeletonRenderer的material, 应直接通过 SkeletonRenderer.CustomMaterialOverride 来访问material覆盖数组, 或者 SkeletonRenderer.CustomSlotMaterials 来访问槽位上的material覆盖数组.

SkeletonGraphicCustomMaterials

该组件是 SkeletonRendererCustomMaterialsSkeletonGraphic 专用版本. 该组件也有检查器界面, 可以为 SkeletonGraphic 设置自定义material和自定义texture覆盖.

右击 SkeletonGraphic 组件, 并选择 Add Basic Serialized Custom Materials 可以将该组件附加到渲染器上. 在 Custom Texture Overrides 数组中添加条目可以替换整个skeleton的texture. 在 Custom Material Overrides 数组中添加条目, 可以保留texture但替换material. 请确保禁用了 Override Enabled 选项, 这样才能让各条目中设置的texture或material覆盖生效.

请注意: 该组件的设计初衷里不包括用代码控制Material覆盖. 如果需要通过代码动态地设置SkeletonGraphic的material, 应直接通过 SkeletonGraphic.CustomMaterialOverride 来访问material覆盖数组, 或者通过 SkeletonGraphic.CustomTextureOverride 访问texture覆盖数组.

SkeletonRenderSeparator

有时需要在角色的各部件之间显示其他的GameObjects, 例如角色爬到树上的过程中应该在树干图层之上显示一条腿, 同时在树干图层之下显示另一条腿. 对此可以使用 SkeletonRenderSeparator 组件, 它能将 SkeletonRenderer 组件(包括其子类 SkeletonAnimation) 分割为多个 SkeletonPartsRenderers, 且可自定义其图层顺序(layer order).

请注意: SkeletonGraphic 组件在 SkeletonGraphic 检查器的 Advanced 面板中直接提供了渲染分割功能, 它实现该功能无需添加任何额外组件.

请注意: 通常情况下, Spine渲染器组件使用单个渲染器显示整个skeleton网格. 不过在其部件(parts)之间就无法插入其他 UnityEngine.Renderers (例如 SpriteRenderer, MeshRenderer, ParticleSystem 等等) 组件了.

设置步骤

  1. 确定Skeleton的绘制顺序(draw order). 确定将Skeleton渲染分割为多个部件的槽位. 为方便起见, 在导出skeleton前应清晰地标注该槽位.

  2. 添加SkeletonRenderSeparator组件 选中Spine GameObject. 在检查器中右击 SkeletonAnimationSkeletonRenderer 组件. 选择 Add Skeleton Render Separator, SkeletonRenderSeparator 组件将被附加到GameObject上.

"Steps 2 to 4"

  1. 指定Separator槽位 这时检查器会显示一个警告, 因为separator列表现在是空的. 你可以在 Separator Slot Names 中选择所需的槽位, 而点击 + 按钮能够添加额外的separator槽位.

    请注意: 该列表实际会在 SkeletonRenderer(及其子类 SkeletonAnimationSkeletonMecanim) 组件中进行序列化, SkeletonRenderSeparator 只是它的一个设置界面.

  2. 添加部件渲染器 此时检查器会显示一个警告:没有部件渲染器. 点击 Add the missing renderers (n) 按钮, 会创建带有 SkeletonPartsRenderer 组件的GameObjects. 运行时会将这些GameObjects自动分配到上面的 Parts Renderers 列表中.

    请注意: SkeletonRenderSeparator 会通过绘制顺序来检测当前所需的部件渲染器数量. 如果在运行时中修改了绘制顺序, 渲染器可能会要求添加额外的部件渲染器. 此时可以点击 Add Parts Renderer 按钮来手动添加部件渲染器.

  3. 设置 Sorting LayerOrder in Layer 每个 SkeletonPartsRenderers 都在检查器中提供了 Sorting LayerOrder in Layer 属性. 每个 SkeletonPartsRenderer 中都能设置排序属性值, 值越大的部件渲染器渲染排序越靠前.

请注意: SkeletonPartsRenderer GameObjects不必作为Spine GameObject的子对象. SkeletonRenderSeparator 会自动维护引用, 所以你大可按需组织场景层次结构.

示例场景

Spine Examples/Other Examples/SkeletonRenderSeparator 中可以找到演示 SkeletonPartsRendererSkeletonRenderSeparator 用法的示例场景.

C#

组件的启用和禁用

默认情况下, SkeletonRenderSeparator 将禁用 SkeletonRenderer 组件并接管其网格渲染工作. 所以当禁用了 SkeletonRenderSeparator 之后, SkeletonRenderer 将重新接管渲染工作.

启用和禁用 SkeletonRenderSeparator 的方法同其他组件一致:

C#
skeletonRenderSeparator.enabled = true; // separation is enabled.
skeletonRenderSeparator.enabled = false; // separation is disabled.

更改分割点

分割点并没有存储在 SkeletonRenderSeparator 中.
它由 SkeletonRenderer 组件(包括其子类 SkeletonAnimationSkeletonMecanim) 中的separator槽位存储. 若需在运行中更改separator槽位, 可以用代码访问 SkeletonRenderer.separatorSlots 列表, 然后像操作普通列表一样调用它的 Add, RemoveClear 方法.

C#
Spine.Slot mySlot = skeletonAnimation.Skeleton.FindSlot("MY SPECIAL SLOT");
skeletonAnimation.separatorSlots.Clear();
skeletonAnimation.separatorSlots.Add(mySlot);

在运行中动态添加SkeletonRenderSeparator

使用静态方法 SkeletonRenderSeparator.AddToSkeletonRenderer 可以添加并初始化一个新的 SkeletonRenderSeparator 组件.

C#
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
skeletonAnimation.SeparatorSlots.Add(mySlot); // see above

// Add the SkeletonRenderSeparator.
SkeletonRenderSeparator skeletonRenderSeparator = SkeletonRenderSeparator.AddToSkeletonRenderer(skeletonAnimation);

它将默认添加当前所需的 SkeletonPartsRenderers 组件. 它也为进阶用例提供了一些可选的参数, 详情请查看 代码文档.

示例组件

spine-unity附带了额外的示例组件, 它们展示了一些进阶用例的解决方案. 下文列出了一些最重要的示例组件.

SkeletonRagdoll

有时需要在一个可动的skeleton上实现类似木偶的布娃娃(Ragdoll)效果, 例如在角色死亡时物理地模拟摔倒. 这可以通过 SkeletonRagdollSkeletonRagdoll2D 示例组件来实现, 它们提供了一个简单界面, 可在SkeletonRenderer 组件(包括其子类 SkeletonAnimationSkeletonMecanim) 上创建布娃娃物理组件.

在示例场景 Spine Examples/Other Examples/SkeletonUtility Ragdoll 中可以找到对 SkeletonRagdoll2D 组件的演示.

SkeletonRenderTexture

适用于需要将skeleton渲染到 RenderTexture 上而非直接渲染到屏幕上的情况, 比如需要 调整透明度来淡出一个skeleton. 该组件可以将skeleton以适当的尺寸和分辨率渲染到 RenderTexture 并显示于合适的四边形中, 如此便能无缝替换掉这个skeleton.

下文中的 SkeletonRenderTextureFadeout 组件需要将一个 SkeletonRenderTexture 或一个 SkeletonGraphicRenderTexture 组件作为输入. 在给GameObject添加了 SkeletonRenderTexture 组件后, 可以再添加一个 SkeletonRenderTextureFadeout 组件来实现淡出效果.

重要提示: 相较于直接将skeleton绘制到帧缓冲区中, 使用RenderTexture中间件进行渲染是开销较大的做法. 只有在必要之处才应使用该组件. 建议保持其禁用状态, 直到你确实需要展示效果的时候再启用它. 例如仅在淡出时启用 SkeletonRenderTexture 组件, 而在其他时间均保持其禁用.

SkeletonGraphicRenderTexture

SkeletonGraphic版的 SkeletonRenderTexture 组件.

SkeletonRenderTextureFadeout

适用于想调整透明度来淡出skeleton, 但又想避免 这类 附件交叠问题的情况. 该组件可以与 SkeletonRenderTextureSkeletonGraphicRenderTexture 组件(需预先添加)搭配使用, 将一个不透明的skeleton渲染到一个临时的 RenderTexture 上, 然后在场景中以渐变不透明度的方式绘制这个 RenderTexture 中的内容.

SkeletonGhost

适用于给角色渲染一个运动轨迹(motion-trail)或运动模糊(motion-blur)效果来模拟速度或力量的情况.SkeletonGhost 组件可以附加在 SkeletonRenderer 组件(包括其子类 SkeletonAnimation) 上, 使用自定义material多次绘制skeleton.

SkeletonUtilityKinematicShadow

适用于需要让某些骨骼带有惯性或响应其他骨骼的运动的情况, 比如让披风以一种更真实的方式跟随角色运动的情况. 此时可以通过 SkeletonUtilityKinematicShadow 组件来实现. 它可以让铰链(hinge chains)从父级transform甚至无关的rigidbody的位置变化中继承速度矢量.

在示例场景 Spine Examples/Other Examples/SkeletonUtility Animated Physics 中可以找到 SkeletonUtilityKinematicShadow 组件的演示.

RenderExistingMesh

适用于试图在不同位置多次渲染同一个可动skeleton来压榨性能的情况, 比如渲染一大群相似的skeleton. 也适用于希望在选中网格后, 用URP着色器 (比如 Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly) 在其下层将它再渲染一次的场景. 该组件可以重新渲染一个已经播放了动画并更新过了的skeleton网格, 由此节省计算动画和计算网格的开销.

RenderCombinedMesh

当skeleton需使用多种material时, 运行时自带的轮廓着色器会渲染出每个子网格的轮廓, 而不会把skeleton作为整体渲染其轮廓. 使用该组件可以合并这些子网格, 并将其作为单个网格来渲染, 从而勾勒出正确的skeleton轮廓.

下一节: 渲染 上一节: 主要组件