spine-runtimes/spine-unity/Assets/Spine/Documentation/4.3-split-component-upgrade-guide-zh.md

20 KiB

spine-unity 4.3 模块化组件升级指南

组件架构重构


📋 本指南的适用范围

本文档仅涵盖 spine-unity 模块化组件迁移流程. 当从 4.2 升级至 4.3 时, spine-csharp 和 spine-unity 中仍包含其他破坏性更改, 在着手模块化组件升级前应先解决这些问题:

  • spine-csharp API 变更: 全新引入的姿态(pose)系统显著地改变了访问骨骼、槽位和约束属性的方式

如需获取涵盖 4.2 至 4.3 所有变更的完整迁移步骤, 请参阅以下官方文档:

重要提示: 请务必优先完成 spine-csharp API 的迁移, 再依据本指南执行模块化组件迁移操作.


⚠️ 重要提醒: 升级前须知

本提醒仅用于升级现有项目, 新项目可忽略本节内容.

升级后将发生的变化

组件将自动升级并分离为相互独立的动画与渲染组件:

  • SkeletonAnimationSkeletonAnimation + SkeletonRenderer 组件
  • SkeletonMecanimSkeletonMecanim + SkeletonRenderer 组件
  • SkeletonGraphicSkeletonAnimation + SkeletonGraphic 组件

所有组件设置与字段将被自动迁移 - 不会造成数据丢失.

但请注意: 由于变更了组件类型, 项目脚本中对原组件的引用可能失效 (例如, SkeletonAnimation 不再继承自 SkeletonRenderer).

必须依序执行的项目升级步骤

  1. 🔒 备份项目 在升级前请完整备份项目. 升级操作将修改场景与预制件文件.

  2. 📖 通读本指南全文 在执行升级操作前, 务必充分理解全部的破坏性变更点.

  3. ✏️ 测试并更新你的代码

    • 更新代码: 根据本指南修正所有引用了 Spine 组件的脚本, 由于类成员已迁移至模块化类, 项目代码将可能无法编译.
    • 测试: 打开若干测试场景, 检查丢了失哪些引用. 未保存的场景仍会保留旧组件数据, 不妨将其作为安全备份——仅当你保存场景后旧组件才会被替换为模块化组件, 此时旧的组件引用便会失效. ⚠️ 警告: 小心对待预制件(Prefab)! 在预制件编辑模式中打开预制件的话, 它会因 Unity 的自动保存机制立即触发组件迁移. 请优先在场景范围内测试, 避免直接操作预制体.
    • 可选操作: 也可以一个个地手动重新分配丢失的引用, 或编写一套自动化迁移脚本(详见下文)来自动迁移组件.

    ⚠️ 重要提示: 自动组件升级仅在 Unity 编辑器打开了场景或预制件时触发. 在构建项目前, 你必须选择 'Upgrade All' 或逐一保存所有场景与预制件来确保没有残留旧组件, 否则可能导致构建中缺失必要组件而失败!

    💡 提示: 若控制台输出信息中包含 "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" 字样,则表明场景中的旧资产已完成自动升级. 此消息将后附日志信息来确认旧组件已成功迁移至模块化组件.

  4. 🔄 选择升级方式

    选项 A - 手动重分配 (推荐小型项目采用):

    • 逐一打开各场景与预制件
    • 在检查器(Inspector)中手动分配缺失的引用
    • 确认无误后保存

    选项 B - 自动化迁移 (推荐含大量场景/预制件的大型项目采用):

    • 首先编写迁移代码:
      • 实现引用迁移模式 (详见下文中的 "防止丢失组件引用" 一节)
      • 对于 SkeletonGraphic 的引用, 请见 "将已有引用迁至 SkeletonAnimation" 一节
    • 在少量文件上测试迁移代码
    • 使用 Upgrade All 按钮:
      • 打开 Edit → Preferences → Spine
      • 在 "Upgrade Scenes & Prefabs" 中
      • 点击 Upgrade All 按钮

若仓促升级可能会导致以下后果

  • 场景或预制件中的 Spine 组件引用在保存后将丢失 (引用被置null)

  • 在未能升级全部场景/预制件便匆忙执行构建, 可能导致构建过程中缺失必要组件而失败

请勿跳过步骤 1-3, 否则项目极有可能遭到破坏.


📦 可选方案: 4.2 版的两阶段迁移

若你正从 spine-unity 4.2 升级至最新版, 建议遵循两阶段迁移方案来隔离潜在问题:

阶段 1: 升级至 4.3-beta 非模块化组件版本

First upgrade to a 4.3-beta version before the component split changes:

这一阶段可以:

  • 优先解决 4.2 → 4.3 spine-csharp API 变更问题, 同时确保项目正常
  • 在升级模块化组件前验证项目稳定性
  • 确认项目在 4.3-beta 下稳定后, 有机会再次备份完整项目, 为阶段 2的迁移工作作出充分准备

阶段 2: 升级至最新的 4.3-beta 模块化组件版本

当项目能够在 4.3-beta 非模块化组件版下稳定工作后:

  • Up升级至最新 4.3-beta 包
  • 按照本指南所述执行模块化组件迁移
  • 处理独立的动画与渲染组件

这种两阶段策略可有效隔离问题源头: 项目出现故障时, 可以明确地判断出是 4.2 → 4.3 的 spine-csharp API 变更导致的, 还是模块化组件所致.


📋 简介

spine-unity 4.3 运行时引入了重大架构变更: 相互独立的动画与渲染组件取代原有的继承结构. 该设计让用户可灵活地选用组件, 例如在项目中让 SkeletonMecanim 负责控制动画, 同时采用 SkeletonGraphic 执行渲染——这是此前无法实现的.

关键更改

  • 模块化组件: 旧组件被拆分为了相互独立的渲染与动画组件.

  • 独立组件架构: SkeletonAnimationSkeletonMecanim 不再继承自 SkeletonRenderer, 而是与独立渲染器组件(ISkeletonRenderer 的子类)协同工作, 例如 SkeletonRendererSkeletonGraphic.

  • 接口更新: 新增了命名统一的 ISkeletonRendererISkeletonAnimation 接口.

  • 设置分组: 网格生成的相关设置集中到了 MeshSettings 属性中.

  • 自动化迁移: 当启用 AUTO_UPGRADE_TO_43_COMPONENTS (此版本默认启用)后, Unity 编辑器将自动升级组件并迁移已废弃的字段.

  • 升级全部场景和预制件: 如需一键升级全部场景与预制件, 请打开 Edit - Preferences - Spine, 并在 Automatic Component Upgrade 中点击 Upgrade Scenes & Prefabs - Upgrade All 即可.

各组件关系

旧架构 新架构
SkeletonAnimation 继承自 SkeletonRenderer SkeletonAnimation + 独立的 SkeletonRenderer 组件
SkeletonMecanim 继承自 SkeletonRenderer SkeletonMecanim + 独立的 SkeletonRenderer 组件
SkeletonGraphic 内置 AnimationState SkeletonGraphic + 独立的 SkeletonAnimation 组件

适配你的代码

以下为各组件的具体变更说明:

▶️ SkeletonRenderer

破坏性变更

1. 接口变更

  • 接口 IHasSkeletonRenderer 中的属性名 SkeletonRenderer 改为 Renderer, 类型由 SkeletonRenderer 改为 ISkeletonRenderer.

2. 事件变更

  • SkeletonRendererDelegate 类型不再为 SkeletonRenderer 的嵌套类型.
    如需修复编译错误, 只需将 SkeletonRenderer.SkeletonRendererDelegate 替换为 SkeletonRendererDelegate.

  • BeforeApply 委托类型由 SkeletonRendererDelegate 更改为 SkeletonAnimationDelegate.

  • SkeletonRendererDelegate 委托签名由 SkeletonRendererDelegate(SkeletonRenderer) 更改为 SkeletonRendererDelegate(ISkeletonRenderer). 该更改会影响以下事件: OnRebuild, OnMeshAndMaterialsUpdated.
    如需修复编译错误, 只需将方法实参从 SkeletonRenderer 更改为 ISkeletonRenderer.

  • 骨骼事件 UpdateLocal, UpdateWorld, 和 UpdateCompleteISkeletonAnimation 类 (SkeletonAnimation, SkeletonMecanim) 迁移至 ISkeletonRenderer (SkeletonRenderer, SkeletonGraphic) 类中. 委托类型由 UpdateBonesDelegate 改为 SkeletonRendererDelegate, 参数由 ISkeletonRenderer 改为了 ISkeletonAnimation.

2. 方法变更

  • LateUpdateMesh() 改为了 UpdateMesh().

  • 移除了 MeshGenerator.TryReplaceMaterials.

3. 执行顺序

  • SkeletonRendererSkeletonGraphic 组件接受 DefaultExecutionOrder(1)] 参数, 以确保其在默认脚本*(即 order=0)*之后执行. 此举保证了即使 UpdateTiming 置为 InLateUpdate, 动画仍能先于 skeleton 更新.

4. 行为变更

  • 在启用 singleSubmesh 后, 现在也会调用 generateMeshOverride.

字段与属性迁移

网格生成器设置

旧 API 新 API 说明
skeletonRenderer.zSpacing skeletonRenderer.MeshSettings.zSpacing 已迁移至 MeshSettings
skeletonRenderer.useClipping skeletonRenderer.MeshSettings.useClipping 已迁移至 MeshSettings
skeletonRenderer.immutableTriangles skeletonRenderer.MeshSettings.immutableTriangles 已迁移至 MeshSettings
skeletonRenderer.pmaVertexColors skeletonRenderer.MeshSettings.pmaVertexColors 已迁移至 MeshSettings
skeletonRenderer.tintBlack skeletonRenderer.MeshSettings.tintBlack 已迁移至 MeshSettings
skeletonRenderer.addNormals skeletonRenderer.MeshSettings.addNormals 已迁移至 MeshSettings
skeletonRenderer.calculateTangents skeletonRenderer.MeshSettings.calculateTangents 已迁移至 MeshSettings

已弃用的小写属性

  • 小写属性 initialFlipX, initialFlipYinitialSkinName 已被弃用并将于后续版本中移除. 请转用同名大写属性 InitialFlipX, InitialFlipYInitialSkinName.

▶️ SkeletonAnimation

破坏性变更

1. 组件架构

  • SkeletonAnimation 现为独立于 SkeletonRenderer 的组件, 不再继承自 SkeletonRenderer.

  • 如需访问渲染器: skeletonAnimation.Renderer.

  • 如需通过渲染器访问动画: skeletonRenderer.Animation.

2. 属性变更

  • state 不再是公开属性. 请转用 AnimationState 属性.

  • 移除了 valid. 请转用 IsValid 属性.

3. 方法变更

  • 新增 UpdateOncePerFrame() - 仅在该帧未调用 Update 时执行更新. 已有的 Update(float time) 保持行为不变.

  • 不再公开无参 Update() 方法, 如需仅在该帧无更新时执行更新, 请使用 UpdateOncePerFrame(), 而 Update(0) 可用于强制执行一次动画更新.

字段与属性迁移

由于 SkeletonAnimation 现已成为独立组件, 曾由 SkeletonRenderer 提供的方法与属性将无法直接通过 SkeletonAnimation 实例访问. 请通过 SkeletonAnimation 实例的 ISkeletonRenderer 访问渲染器属性 skeletonAnimation.Renderer, 而 skeletonRenderer.Animation 属性则可通过 SkeletonRendererSkeletonGraphic 实例中的 ISkeletonAnimation 访问. 对于未在 ISkeletonRenderer 接口中暴露的成员, 可将 skeletonAnimation.Renderer 显式转换为 SkeletonRendererSkeletonGraphic 以访问渲染器成员变量.

示例代码

// 升级前: 直接访问 SkeletonRenderer 属性
skeletonAnimation.zSpacing = 0.1f;
skeletonAnimation.AnySkeletonRendererProperty;

// 升级后: 通过 Renderer 对象访问
skeletonAnimation.Renderer.MeshSettings.zSpacing = 0.1f; // 访问 ISkeletonRenderer 接口暴露出的成员
var skeletonRenderer = (SkeletonRenderer)skeletonAnimation.Renderer;
skeletonRenderer.AnySkeletonRendererProperty; // 访问 ISkeletonRenderer 接口未暴露的成员


▶️ SkeletonMecanim

破坏性变更

1. 组件架构

  • SkeletonMecanim 现为独立于 SkeletonRenderer 的组件, 不再继承自 SkeletonRenderer.

  • 访问方式同 SkeletonAnimation.

2. 方法变更

  • 不再公开 Update().

  • 请改用 UpdateIfNecessary(), 如需强制更新请使用 Update(0).

字段与属性迁移

与上文中的 SkeletonAnimation 相同

▶️ SkeletonGraphic

破坏性变更

1. 组件架构

  • SkeletonGraphic 不再涉及动画逻辑, 请额外添加 SkeletonAnimation 组件以使用动画.

  • 如需访问动画: skeletonGraphic.Animation.

2. 将已有引用迁至 SkeletonAnimation

若你组件仅通过引用 SkeletonGraphic 来修改其动画属性, 那么建议将引用类型更改为 SkeletonAnimation. 此举便可直接访问动画状态而无需像 ((SkeletonAnimation)skeletonGraphic.Animation).AnimationState 这样进行显式转换, 例如: skeletonAnimation.AnimationState. 请注意, 若希望重命名序列化组件变量, 可在变量声明前添加 [FormerlySerializedAs("previousName")] 特性, Unity 将自动将原字段中保存的序列化值迁移至新变量, 从而保留你在场景或预制件中的已有配置.

示例代码

// Automatically reassign previous serialized values
[FormerlySerializedAs("skeletonGraphic")]
public SkeletonAnimation skeletonAnimation; // Will maintain the reference after upgrade

3. 属性变更

  • 已移除属性 AnimationState - 请通过 SkeletonAnimation 组件查询该属性.

  • 不再公开 MeshGenerator - 请改用 MeshSettings 属性和 SetMeshSettings() 方法.

  • MaterialsMultipleCanvasRenderers 类型由 ExposedList<Material> 改为 Material[].

4. 创建辅助器(Creation Helper)方法

  • NewSkeletonGraphicGameObject 现在默认同时创建 SkeletonGraphicSkeletonAnimation, 以对齐原有行为. 返回类型改为了一个包含了这两个组件引用的结构体.

  • 已移除 AddSkeletonGraphicComponent, 可用替换为:

    • AddSkeletonGraphicAnimationComponents - 同时创建 SkeletonGraphicSkeletonAnimation 组件.
    • AddSkeletonGraphicRenderingComponent - 仅创建 SkeletonGraphic 组件.

5. 事件更改

  • 委托签名从 SkeletonRendererDelegate(SkeletonGraphic) 改为 SkeletonRendererDelegate(ISkeletonRenderer). 该更改会影响以下事件: OnRebuild, OnMeshAndMaterialsUpdated.
    如需修复编译错误, 只需将方法实参从 SkeletonGraphic 更改为 ISkeletonRenderer.

6. 执行顺序

  • SkeletonRendererSkeletonGraphic 组件现可接收 DefaultExecutionOrder(1)] 参数,, 以确保其在默认脚本*(即 order=0)*之后执行. 此举保证了即使 UpdateTiming 置为 InLateUpdate, 动画仍能先于 skeleton 更新.

7. 行为变更 - Material 更新

  • CanvasRenderer 的 material 不再于每个 LateUpdate 中更新, 而仅在以下情况时更新:
    • a) 当 skeleton 更新需更换 materials, 或者
    • b) 代码访问了 CustomMaterialOverrideCustomTextureOverride 并可能修改它们.

字段与属性迁移

A动画属性

旧 API 新 API 说明
skeletonGraphic.AnimationState ((SkeletonAnimation)skeletonGraphic.Animation).AnimationState 需显式转换
skeletonGraphic.startingAnimation skeletonAnimation.AnimationName 通过 Animation 组件访问
skeletonGraphic.startingLoop skeletonAnimation.loop 通过 Animation 组件访问
skeletonGraphic.timeScale skeletonAnimation.timeScale 通过 Animation 组件访问
skeletonGraphic.unscaledTime skeletonAnimation.unscaledTime 通过 Animation 组件访问

网格生成器设置

旧 API 新 API 说明
skeletonGraphic.MeshGenerator.settings skeletonGraphic.MeshSettings 直接访问设置

⚠️ 其他重要注意事项

防止丢失组件引用

其他组件(例如 SkeletonRenderSeparator)若持有对 SkeletonRenderer 的引用, 且其目标引用曾为 SkeletonAnimationSkeletonMecanim, 则升级后该引用将被置为 null. 这是由于 SkeletonAnimationSkeletonMecanim 不再继承自 SkeletonRenderer, 因而不再构成有效的类型引用. 对此, 手动解决方案是直接不管, 变量类型保持 SkeletonRenderer 不变, 任凭 SkeletonAnimation 的引用被置为 none. 随后再在各场景与预制件中手动分配丢失的引用. 而半自动方案则是: 将项目中 SkeletonRenderer 变量的类型改为 Component (保持对象引用避免丢失目标), 新增一个类型为 SkeletonRenderer(或 SkeletonAnimation)的变量,然后在代码中从 Component 类型变量读取目标对象, 并将其赋给新变量. 例如, 在 Unity 编辑器中给组件添加 [ExecuteAlways] 特性标记, 并在 Awake() 方法中自动执行此操作.

示例代码

// 升级前的类代码
public class TestMigrateReferences : MonoBehaviour {
public SkeletonRenderer skeletonRenderer; // 赋给这个 SkeletonAnimation 的引用将在升级后丢失.

public void Foo () {
skeletonRenderer.skeleton.ScaleX = -1;
}
}

// 升级后的类代码
[ExecuteAlways] // 或者用 [ExecuteInEditMode]
public class TestMigrateReferences : MonoBehaviour {
#if UNITY_EDITOR
[SerializeField, HideInInspector, FormerlySerializedAs("skeletonRenderer")] Component previousSkeletonRenderer; // 如此便能捕获原名为 skeletonRenderer 的 `SkeletonAnimation` 引用.
#endif
public SkeletonRenderer skeletonRenderer;

public void Foo () {
skeletonRenderer.skeleton.ScaleX = -1;
}

#if UNITY_EDITOR
public void Awake () {
AutoUpgradeReferences();
}

public void AutoUpgradeReferences () {
if (previousSkeletonRenderer != null && skeletonRenderer == null) {
 skeletonRenderer = previousSkeletonRenderer.GetComponent<SkeletonRenderer>();
 if (skeletonRenderer != null)
  Debug.Log("Upgraded SkeletonRenderer reference.");
}
}
#endif
}

组件的启用/禁用

由于 ISkeletonRendererISkeletonAnimation 组件现已一分为二, 任何控制组件启用/禁用的脚本都必须同时启用/禁用这两个组件.

SkeletonUtilityBone 行为更改

在 Override 模式下, SkeletonUtilityBone 仅在 UpdatePhase.Complete 阶段调整变换(Transform), 不再于 UpdatePhase.World 阶段重复更新, 以减少冗余操作.

自动化迁移

  • 当启用了 AUTO_UPGRADE_TO_43_COMPONENTS 后, Unity 编辑器将自动迁移废弃字段.
  • 如需一键升级全部场景与预制件, 请打开 Edit - Preferences - Spine, 并在 Automatic Component Upgrade 中点击 Upgrade Scenes & Prefabs - Upgrade All 即可.
  • 各类中的 UpgradeTo43TransferDeprecatedFields() 方法负责其各自的序列化数据的迁移.
  • 运行时访问仍需手动更新代码.

常见变更总结

  1. 添加 .Renderer. 前缀便可从动画组件访问渲染属性.
  2. 添加 .MeshSettings. 前缀可以访问网格生成设置.
  3. 从 SkeletonGraphic 访问 AnimationState 时, 需 显式类型转换为 SkeletonAnimation.
  4. 更新委托方法签名: 签名中的具体类型应改为接口类型.
  5. 使用上述迁移模式升级后要重新绑定丢失的引用.

禁用自动升级检查

当完成了 Spine 资源、场景和预制件的全部迁移工作后, 可禁用自动升级检查来提升编辑器性能:

  1. 转到 Edit → Preferences → Spine
  2. Automatic Component Upgrade 中点击 Split Component UpgradeDisable

此操作将停止 Unity 编辑器在加载场景或预制件时的迁移检测. 如有新资源需要迁移, 可随时重启此功能.


需要帮助?

若在迁移过程中遇到棘手问题, 或发现组件迁移有误, 请前往 Spine 论坛 发帖反馈. 我们将全力协助,确保自动迁移过程尽可能顺畅无痛.